Java garbage collection with recursive function

I know that objects become inaccessible and are marked for garbage collection at each iteration of the regular loop. What about recursive calls? Sort of:

public void doWork() { Object a = new Object(); ....some work with a... this.sleep(60000); doWork(); } 

Is the object (i.e. 'a') in the first recursion marked for the garbage collection after the start of the second recursion or should it be explicitly marked as null, since the outer function never ends due to recursion.

+4
source share
6 answers

During each recursive call, local variables (here the "a" link) are pushed onto the stack. The local variable is the root of the GC. During the second recursive call, the new link is pushed onto the stack. However, the first link still exists, and thus the object is still accessible and therefore cannot be garbage collected.

Thus, if you want the first created object to be marked for garbage collection (until the function is finished), you must explicitly set "a" to null.

Here is a useful link for understanding GC: http://javabook.compuware.com/content/memory/how-garbage-collection-works.aspx

+2
source

You should assume that all local links are alive while the method itself is in the call stack. This means that you get one live link to a for each recursion.

It may happen that the runtime sees that the slot for variable a can be overwritten when it is no longer available. In this case, it becomes inaccessible even if doWork () has not returned yet. However, you cannot rely on this. This would help a = null; immediately after the last use.

0
source
Theoretically, recursion is performed by pushing the actual frame (a local set of variables) onto the stack and opening a new frame for a new execution.

The object on the heap still refers to the variables in the frame that was pushed onto the stack, which means that for the GC, the object is still β€œlive”.

However, many compilers (and I also assume that javac) are able to recognize and deploy tail recursions, similar to those shown in the example, which greatly simplifies recursion, freeing up many resources.

In general, however, recursion uses a lot of stack and heaps of space, and therefore using recursion is not always a good idea.

0
source

This is a good approach to actively getting rid of links if you want garbage collection by setting the variables to null . However, do not forget that objects can contain event logging, separate streams, etc. Therefore, if you want to collect an object for garbage collection, you must make sure that their links are not leaked. This does not apply to Object , but it can happen to instances from other classes. Regarding the question, though, I believe that this is not garbage collection unless you actively get rid of its link, but I have not tested this with all versions of Java.

0
source

I found that local variables that reference objects constitute garbage if they are no longer needed. However, this does not apply during debugging. I think the debugger keeps a link to it, but in normal execution it does not need it.

Try the following code and see what happens.

 Object o1 = new Object(); System.out.println(o1); WeakReference<Object> wr = new WeakReference<Object>(o1); System.gc(); System.out.println(wr.get()); 

My conclusion (without debugger):

 java.lang.Object@20662d1 null 

My conclusion (with debugger):

 java.lang.Object@206b4fc java.lang.Object@206b4fc 

Thus, it would seem that earlier links are garbage collection, even if the local method is still on the stack.

0
source

Is the object (i.e. 'a') in the first recursion marked for the garbage collection after the start of the second recursion or should it be explicitly marked as null, since the outer function never ends due to recursion.

Answer: it depends on the platform.

The variable a is still in scope until the doWork() declaration instance is returned. On the other hand, it is obvious to us that by the time that the variable a cannot affect the calculation as soon as we reach the recursive call, and (theoretically), this means that the GC no longer needs to consider it for purposes of determining reachability.

So it boils down to whether the JVM is smart enough to realize that a doesn't matter anymore. It depends on the platform. And as another answer notes, working with a debugger application can change that.


Another answer mentions tail call optimization. Of course, if the JVM performed this optimization, then the "old" a will conceptually be replaced by the "new" in the optimized "call". However, none of JSM HotSpot (at least prior to Java 8) implements tail call optimization, since optimization will interfere with Java code, which relies on the ability to count stack frames; for example, a security code.

However, if this particular code was a significant storage leak, then it is likely to be controversial because (in the absence of tail call optimization) the code will most likely give you a StackOverflowError before it fills the heap.

0
source

Source: https://habr.com/ru/post/982142/


All Articles