JDK-8135322 : ConstantPool::release_C_heap_structures not run in some circumstances
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 8u66
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-09-10
  • Updated: 2017-12-10
  • Resolved: 2016-05-19
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
8u112Fixed 9 b122Fixed
Related Reports
Relates :  
Relates :  
Relates :  
JDK 8 is leaking memory in VM_RedefineClasses::merge_cp_and_rewrite when repeating class redefinition:

[0x00002aaaab1c2d5a] ConstantPool::ConstantPool(Array<unsigned char>*)+0x6a
[0x00002aaaab1c307c] ConstantPool::allocate(ClassLoaderData*, int, Thread*)+0x14c
[0x00002aaaab48aa7e] VM_RedefineClasses::merge_cp_and_rewrite(instanceKlassHandle, instanceKlassHandle, Thread*)+0x5e
[0x00002aaaab48b5d3] VM_RedefineClasses::load_new_class_versions(Thread*)+0x4c3
            (malloc=84362KB #719885) 
For JDK 9 ConstantPool::release_C_heap_structures is not run either. It has no lock to leak, but a call to ConstantPool::unreference_symbols done there will never be called.

After discussing this with Stefan Karlsson, I'm convinced that it is the above change that fixed the memory leak. Usually, a direct free of a constant pool is not needed if the holding ClassLoaderData is going away, since memory is reclaimed automatically because it's part of the metaspace. However, a lock allocated in the constant pool (introduced by JDK-8014910, removed in JDK 9 by JDK-8026977) is not part of the metaspace, and can therefore be leaked under the circumstances mentioned above (classloader marked as not live).

The leak fixed in JDK-8026977 might also be unrelated - I can't really tell without further investigation, since the NMT detail tracking was not finished in that build.

Looks like it was JDK-8026977 that fixed it in JDK 9. It might be a bit problematic to backport, so I'll probably do a JDK 8 specific fix for the leak.

Doesn't look like its JDK-8061205 that fixed this in JDK 9, still working on finding out which change it was.

This is because the merge constant pool used by class redefinition is not removed properly, even though it's added to the classloader _deallocate_list. I think this is because ClassLoaderDataGraph::do_unloading removes the related classloader from the graph because it is not live, and then runs the ClassLoaderData destructor without cleaning out the _deallocate_list first. This is fixed in 9, most likely by JDK-8061205. Working on verifying that. Two ways of fixing this, either make sure the _deallocate_list is cleaned in ClassLoaderData::~ClassLoaderData, or backport JDK-8061205. Changing this to hotspot/runtime since that's what JDK-8061205 is set to.

Moved to core-svc/java.lang.instrument since the test case appears to use JLI/JPLIS... Update: If the leak is due to something in the JVM/TI layer, then this bug should be moved to hotspot/jvmti.