Duplicate :
|
|
Duplicate :
|
|
Relates :
|
|
Relates :
|
The attached test (v4) shows that C2 scalar replacement (-XX:+EliminateAllocations) can prevent JVMTI agents from finding a memory leak using JVMTI FollowReferences(). The required JVMTI capability can_tag_objects is an 'always' capability, meaning an agent can request it during the live phase. This allows for loading an agent dynamically into the vm to do heap diagnostics. Therefore it is not sufficient to disable scalar replacement when can_tag_objects is taken by an agent. The test shows this also. This bug report duplicates JDK-8230956, but it is supposed to be less theoretical giving an example that is close to real world scenarios and it shows, that just disabling escape analysis is not sufficient. Steps performed by the test: // Please use v4. Previous versions are obsolete. - Warmup: call dontinline_leakHoldingMethodWithScalarReplacement(long leakSize) often with small leak size to get it compiled by C2. - After warmup call dontinline_leakHoldingMethodWithScalarReplacement(long leakSize) again with Long.MAX_VALUE as target leak size. - In that call create and inflate a new leak, linking new LeakObject instances into a list which is rooted at an object referenced by the local variable 'holder'. - This 'holder' object is allocated at the entry of dontinline_leakHoldingMethodWithScalarReplacement(long leakSize). C2 eliminated this allocation based on proof by escape analysis that the created object is local to the compiled method. The scalar field values are used directely be the compiled code (scalar replacement). - Continue inflating until until {@link OutOfMemoryError} is thrown. - Catch the OOM in {@link #dontinline_allocateNewLeakObj()} and dynamically load the agent to create a class histogram of reachable heap objects. This can be done, because the capability can_tag_objects required for JVMTI FollowReferences() can be added during the live phase. - Call into the agent which uses JVMTI FollowReferences() to sum up used bytes per class of reachable objects. The implementation of FollowReferences() misses scalar replaced objects and consequently all leaked objects too. - Control returns to dontinline_leakHoldingMethodWithScalarReplacement(long leakSize) and an uncommon trap is hit. - The compiled frame is replaced with interpreter frames. Scalar replaced objects are reallocated on the heap. - Capture 2nd class histogram. This one shows the leak, because the holder was reallocated on the heap. - Store the root object 'holder' into a static variable. Because of this store the holder object was and is "definitively reachable" in the sense of JLS 12.6 Finalization of Class Instances. - Capture 3nd class histogram. It contains the leak as well. - Delete reference to the leak. - Capture 4th class histogram. It shows that the leak became unreachable.
|