JDK-8173594 : jvmti heap dump reporting wrong object liveness info
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: 8
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2017-01-27
  • Updated: 2018-07-05
  • Resolved: 2017-09-06
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.
JDK 11
11Resolved
Related Reports
Duplicate :  
Relates :  
Description
from openjdk-gc-user:
"Hello,

I am working on a closed source software that uses a patched version of apache-batik to display SVG-Documents one by one. If you keep loading and discarding some specific SVG-Documents memory consumption keeps on growing until it reaches more than 95% of the available memory. The application becomes unusable slow, very little memory gets freed, although the gc is constantly running. Sometimes an OutOfMemoryError gets thrown. I took memory snaphsots and analyzed them using jvisualvm and yourkit. These tools report the majority of the memory as unreachable.
I have tried different garbage collectors (G1,ConcurrentMarkSweep),
and different Versions of Java: 1.8_60;1.8_65;1.8_102, the issue is always reproducible.
Is there something i can do to debug this further? I am currently not able to reproduce this issue in a somewhat small self contained example.
I could provide gc-logs and the heap dump (about 1gb zipped) or any other debuging info if someone is interested."

I am able to reproduce this with a micro. It might be related how gc reports object liveness when traversing the heap.

May assign to gc if needed.

Comments
Closing as a duplicate. Thank you Jenny for helping me with YourKit and looking at the heap dump info.
06-09-2017

Is this actually a duplicate of JDK-8081323 ?
25-08-2017

Yes, the objects in the resolved_references will be found, but that's not what's broken. The problem is that we don't report _why_ they are kept alive. [~coleenp] No, I didn't dig deep enough to find all paths to the "leaking" objects.
21-03-2017

The resolved_references and the oops in CLD::_handle should be reached by this, since they're in the heap. HeapObjectDumper obj_dumper(this, writer()); Universe::heap()->safe_object_iterate(&obj_dumper); [~stefank] Did you find the leak?
17-03-2017

Thorsten Goetzke provided a micro to reproduce this issue. ==== Hello, Back in January i posted about Unreachable Objects not claimed by the gc, i am finally able to produce a micro, see below. When I run the class below using -Xmx4g and take a memory snaphsot (hprof or yourkit, doesnt matter), I will see 2 LeakImpl Objects. These Objects have no reported path to root, yet they won't be collected. If i lower the heap space to -Xmx2g the Application throws java.lang.OutOfMemoryError: Java heap space. @Jenny Zhang should I create a new bugreport, or will you take care of this? Best Regards, Thorsten Goetzke package de.frei.demo; import jdk.nashorn.api.scripting.NashornScriptEngine; import jdk.nashorn.api.scripting.NashornScriptEngineFactory; import javax.script.CompiledScript; import javax.script.ScriptException; import javax.script.SimpleBindings; import java.util.function.Function; public final class LeakDemo { private static NashornScriptEngine ENGINE = getNashornScriptEngine(); private static CompiledScript SCRIPT; public static void main(String[] args) throws Exception { simulateLoad(); simulateLoad(); System.gc(); Thread.sleep(1000000); } private static void simulateLoad() throws ScriptException { final CompiledScript compiledScript = getCompiledScript(ENGINE); compiledScript.eval(new SimplestBindings(new LeakImpl())); } private static NashornScriptEngine getNashornScriptEngine() { final NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); final NashornScriptEngine scriptEngine = (NashornScriptEngine) factory.getScriptEngine(); return scriptEngine; } private static CompiledScript getCompiledScript(final NashornScriptEngine scriptEngine) throws ScriptException { if (SCRIPT == null) { SCRIPT = scriptEngine.compile(" var pivot = getItem(\"pivot\");"); } return SCRIPT; } public interface Leak { LiveItem getItem(String id); } public static final class LeakImpl implements Leak { private final byte[] payload = new byte[1024 * 1024 * 1024]; @Override public LiveItem getItem(final String id) { return new LiveItem() { }; } } public interface LiveItem { } public static final class SimplestBindings extends SimpleBindings { public SimplestBindings(Leak leak) { put("getItem",(Function< String, LiveItem>) leak::getItem); } } }
28-02-2017

Signers and protection domain were moved to the instance of java.lang.Class so are found in normal heap walking. They are also reported with JVMTI_REFERENCE_SIGNERS and JVMTI_REFERENCE_PROTECTION_DOMAIN separately. I think these were specified in the spec because they happened to be in the Klass* metadata at the time.
06-02-2017

There seems to be at least two known issues with the heap dumper: 1) Not all GC roots are reported. Compare VM_HeapDumper::doit with, for example, PSMarkSweep::mark_sweep_phase1. 2) Not all indirect references from Object -> Metadata - > Object are reported. There are some special cases, for example, signers and protection domain, but others like the resolved references in ClassLoaderData::_handles are not reported. Could the first issue be solved by reporting HPROF_GC_ROOT_UNKNOWN for the missing roots? Some VM anonymous classes are artificially kept alive while they are being setup. SystemDictionary::always_strong_classes_do doesn't visit these classes, but ClassLoaderDataGraph::always_strong_classes_do does. Depending on what the intention of HPROF_GC_ROOT_STICKY_CLASS is, we might want to use ClassLoaderDataGraph instead. Regarding the second issue, see this bug for a similar problem that was solved by introducing a redundant usage of the ClassLoader.classes because Class -> Klass -> ClassLoaderData -> ClassLoader (Object -> Metadata -> Metadata -> Object) wasn't reported correctly in FollowReferences: https://bugs.openjdk.java.net/browse/JDK-7197269
31-01-2017

Reattached the test.tar.gz(with mapSpain.svg). To reproduce with jdk8 tar xvfz test.tar.gz java -Xmx1g -XX:+UseG1GC -XX:+PrintGCDetails -Xloggc:./gc-jdk8.log -jar ./loadSvg.jar mapSpain.svg 6000 Note I did not print the exception stacktrace, so it may seems like the it is hanging. From gc log, it settles (on my machine) after 36 seconds, when it stops loading nodes and throw exceptions. Then I did a heap dump jcmd <pid> GC.heap_dump -all h1-all.hprof Open this heap dump with yourkit, there are >50m of unreachable objects. But the gc logs at this time shows: [Eden: 610.0M(610.0M)->0.0B(611.0M) Survivors: 4096.0K->3072.0K Heap: 613.6M(1024.0M)->4760.7K(1024.0M)] And no gc due to this heap dump. If I do jcmd <pid> GC.heap_dump h1-live.hprof, gc log has 156.617: [Full GC (Heap Dump Initiated GC) 66M->9279K(31M), 0.0722641 secs] [Eden: 62.0M(611.0M)->0.0B(16.0M) Survivors: 3072.0K->0.0B Heap: 66.7M(1024.0M)->9279.6K(31.0M)], [Metaspace: 13314K->13314K(1060864K)] And heap dump shows 9M of live objects. This might not be the issue the Thorsten (from gc-user list) is facing. From his update: "I have an update. It seems like the unreported/errorous gc Root is somewhere near "securiton.uls.tools.configuration.plugins.graphic.zoneeditor.data.svg.dynamics.impl.LiveItemImpl". I aggressivly nulled out the fields of instances of this Object and now the gc frees sufficient memory. It seems like the LiveItemImpl Objects themself are still leaking without any paths from gc root, but they no longer keep millions of Nodes alive causing our Application to go OutOfmemory within minutes. The Root Cause seems like something Nashorn is doing is confusing the JVM/GC to not free up memory in some specific circumstances. The LiveItemImpl Objects have incoming references from the internals of the nashorn framework. " Maybe both are cases for inaccurate report.
30-01-2017

When it all settled, gc log has [Eden: 609.0M(609.0M)->0.0B(612.0M) Survivors: 5120.0K->2048.0K Heap: 613.9M(1024.0M)->3802.1K(1024.0M)] with jcmd <pid> GC.heap_dump -all h1-all.hprof the heap dump shows 59,739,104-byte unreachable and 9150796byte strongly reachable.
28-01-2017

the micro is copied from http://stackoverflow.com/questions/26027313/how-to-load-and-parse-svg-documents, with some modification. private Document createSVGDocument( String uri, int numChildren ) throws IOException { String parser = XMLResourceDescriptor.getXMLParserClassName(); SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory( parser ); Document doc = factory.createDocument( uri ); for (int i=0; i<numChildren;i++) { Document otherDocument = factory.createDocument(uri); DocumentFragment docFrag = otherDocument.createDocumentFragment(); try { docFrag.appendChild(doc.getDocumentElement()); } catch (DOMException ex) { //ex.printStackTrace(); } } and in run(), sleep for 300sec, instead of printing the path. to run java -Xmx1g -XX:+UseG1GC -XX:+PrintGCDetails -Xloggc:./gc-jdk8.log -jar ./loadSvg.jar mapSpain.svg 6000
28-01-2017

Serguei, Thanks for your comment. As I mentioned in the first comment, it might be a gc bug. Thanks for reassign. I think this is the same in jdk9. However, I have not figured out how to run in jdk9, some classes not found. I changed to jdk8
28-01-2017

Moved to GC for initial evaluation. This bug has nothing to do with the JVMTI.
28-01-2017

Jenny, you may need to use some memory leak detection tool. But I wonder why have you filed this bug on hotspot/jvmti? Also, why the "Affects Version" is 9 if you run your app with the 8 updates?
28-01-2017