When is a Java local variable eligible for GC?

前端 未结 6 1422
被撕碎了的回忆
被撕碎了的回忆 2021-01-06 01:11

Given the following program:

import java.io.*;
import java.util.*;

public class GCTest {

    public static void main(String[] args) throws Exception {
             


        
相关标签:
6条回答
  • 2021-01-06 01:37

    As test is only used once, it can be removed immediately after the call to it. Even if the each call to read used a call to getInputStream instead of using the local is variable, use of the object could be optimised away. FIleInputStream cannot be finalised prematurely due to its use of locking. Finalisers are difficult.

    In any case, your finaliser is pointless. The underlying FileInputStream will close itself on finalisation anyway.

    0 讨论(0)
  • 2021-01-06 01:45

    Slightly off-topic, but finalize() should never be used to close() a file. The language does not guarantee that finalize() will ever get called. Always use a try ... finally construct to guarantee file closure, database cleanup, etc.

    0 讨论(0)
  • 2021-01-06 01:47

    While the object won't be garbage collected if it is still in scope, the JIT compiler might take it out of scope if the variable isn't actually used any further in the code (hence the differing behavior you are seeing) even though when you read the source code the variable still seems to be "in scope."

    I don't understand why you care if an object is garbage collected if you don't reference it anymore in code, but if you want to ensure objects stay in memory, the best way is to reference them directly in a field of a class, or even better in a static field. If a static field references the object, it won't get garbage collected.

    Edit: Here is the explicit documentation you are looking for.

    > I'm assuming an object cannot die before a local reference to it has gone out of scope.

    This can not be assumed. Neither the Java spec nor the JVM spec guarantees this.

    Just because a variable is in scope, doesn't mean the object it points to is reachable. Usually it is the case that an object pointed to by an in-scope variable is reachable, but yours is a case where it is not. The compiler can determine at jit time which variables are dead and does not include such variables in the oop-map. Since the object pointed to by "nt" can [sic - should be cannot] be reached from any live variable, it is eligible for collection.

    0 讨论(0)
  • 2021-01-06 01:52

    In theory Test must not be in the scope since it is at the method level run() and the local variables should be garbage collected as you come out of the method.However you are storing the results in list, and i have read it somehere that lists are prone for storing weak references that are not garbage collected easily (depending on jvm implementation).

    0 讨论(0)
  • 2021-01-06 01:54

    I recommend that you and your co-worker read the The Truth About Garbage Collection.

    Right at the start, it says this:

    The specification for the Java platform makes very few promises about how garbage collection actually works. [elided]

    While it can seem confusing, the fact that the garbage collection model is not rigidly defined is actually important and useful-a rigidly defined garbage collection model might be impossible to implement on all platforms. Similarly, it might preclude useful optimizations and hurt the performance of the platform in the long term.

    In your example, the test variable becomes "invisible" (see A.3.3 of above) in the while loop. At this point some JVMs will continue to view the variable as containing a "hard reference", and other JVMs will treat it as if the variable has been nulled. Either behaviour is acceptable for a compliant JVM

    Quoting from the JLS edition 3 (section 12.6.1 paragraph 2):

    A reachable object is any object that can be accessed in any potential continuing computation from any live thread.

    Notice that reachability is not defined in terms of scopes at all. The quoted text continues as follows:

    Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.

    (My emphasis added.) This means that an object object may be garbage collected and finalization may occur earlier or later than you would expect. It is also worth noting that some JVMs take more than one GC cycles before unreachable objects are finalized.

    The bottom line is that a program that depends on finalization happening earlier or later is inherently non-portable, and to my mind buggy.

    0 讨论(0)
  • 2021-01-06 01:59

    What are you observing that you find strange? Each time you execute run(), you create a new instance of Test. Once run completes, that instance of test is out of scope and eligible for garbage collection. Of course "eligible for garbage collection" and "is garbage collected" are not the same thing. I'd expect that if you run this program, you'd see a bunch of finalize messages scroll by as invocations of run complete. As the only console output I see is these messages, I don't see how you would know which instance of Test is being finalized when you see each message. You might get more interesting results if you added a println at the beginning of each invocation of run, and maybe even added a counter to the Test object that gets incremented each time a new one is created, and which is output with the finalize message. Then you could see what was really happening. (Well, maybe you're running this with a debugger, but that could also obscure more.)

    0 讨论(0)
提交回复
热议问题