Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java lambdas heap dump - Instance of lambda not getting garbage collected

I am facing some problems with garbage collection while generating an application in java, where I use Stream.map to trim all the elements in the list. The instances of anonymous lambda class exist in the heap dump even though the instance of the enclosing class is 0 as shown in the snap of visual VM.

enter image description here

The LambdaTesting class:

class LambdaTesting {

    protected List<String> values;

    protected LambdaTesting(List<String> values) {
        this.values = values;
    }
    public List<String> modify() {      
        return this.values.stream().map(x -> x.trim()).collect(Collectors.toList());
    }
    public List<String> modifyLocal() {
        List<String> localValue = new ArrayList<>();
        localValue.add("Local FOO ");
        localValue.add("Local BAR ");
        return localValue.stream().map(x -> x.trim()).collect(Collectors.toList());     
   }
}

The method which creates the instance of LambdaTesting and invokes these methods:

public List<String> testMethods() {
    List<String> test = new ArrayList<>();      
    test.add("Global FOO  ");
    test.add("   GLOBAL BAR");  
    LambdaTesting lambdaTesting = new LambdaTesting(test);
    lambdaTesting.modifyLocal();
    lambdaTesting.modify();
}

The thread dump was taken after putting a debug point at the next line after testMethods is invoked.

Why are the references to Lambda still present in the heap dump?

like image 210
Akhil Avatar asked Jun 02 '20 19:06

Akhil


People also ask

How does Java know when to garbage collect?

In Java, garbage collection happens automatically during the lifetime of a program. This eliminates the need to de-allocate memory and therefore avoids memory leaks. Java Garbage Collection is the process by which Java programs perform automatic memory management.

When exactly JVM runs garbage collector?

When the JVM doesn't have necessary memory space to run, the garbage collector will run and delete unnecessary objects to free up memory. Unnecessary objects are the objects which have no other references (address) pointing to them.

How often the heap memory is garbage collected?

The heap is created when the JVM starts up and may increase or decrease in size while the application runs. When the heap becomes full, garbage is collected. During the garbage collection objects that are no longer used are cleared, thus making space for new objects.


1 Answers

As elaborated in Does a lambda expression create an object on the heap every time it's executed?, a non-capturing lambda expression will be remembered and reused, which implies that it is permanently associated with the code that created it. That’s not different to, e.g. string literals whose object representation stays in memory as long as the code containing the literal is alive.

This is an implementation detail. It doesn’t have to be that way, but the reference implementation and hence, all commonly used JREs do it that way.

A non-capturing lambda expression is a lambda expression that uses no (non-constant) variables of the surrounding context and does not use this, neither implicitly nor explicitly. So it bears no state, hence, consumes a tiny amount of memory. There is also no possibility to create a leak regarding other objects, as having references to other objects is what makes the difference between non-capturing and capturing lambda expressions and likely is the main reason why capturing lambda expressions are not remembered that way.

So the maximum number of such never-collected instances is equal to the total number of lambda expression in your application, which might be a few hundred or even thousands, but still small compared to the total number of objects the application will ever create. As explained in Function.identity() or t->t, putting a lambda expression into a factory method instead of repeating it in the source code, can reduce the number of instances. But given the rather small total number of objects, that’s rarely a concern. Compare with the number of the already mentioned string literals or the Class objects which already exist in the runtime…

like image 155
Holger Avatar answered Oct 19 '22 06:10

Holger