JDK-8244203 : sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java fails with NullPointerException
  • Type: Bug
  • Component: hotspot
  • Sub-Component: svc-agent
  • Affected Version: 15
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2020-04-30
  • Updated: 2024-09-28
  • Resolved: 2020-05-22
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 15
15 b25Fixed
Related Reports
Relates :  
Description
java.lang.NullPointerException
	at jdk.hotspot.agent/sun.jvm.hotspot.oops.NarrowOopField.getValueAsOopHandle(NarrowOopField.java:49)
	at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.writeField(HeapHprofBinWriter.java:1042)
	at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.writeFieldDescriptors(HeapHprofBinWriter.java:981)
	at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.writeClassDumpRecord(HeapHprofBinWriter.java:663)
	at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter$1.visit(HeapHprofBinWriter.java:600)
	at jdk.hotspot.agent/sun.jvm.hotspot.classfile.ClassLoaderData.classesDo(ClassLoaderData.java:105)
	at jdk.hotspot.agent/sun.jvm.hotspot.classfile.ClassLoaderDataGraph.classesDo(ClassLoaderDataGraph.java:84)
	at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.writeClassDumpRecords(HeapHprofBinWriter.java:596)
	at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.write(HeapHprofBinWriter.java:442)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.JMap.writeHeapHprofBin(JMap.java:182)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.JMap.run(JMap.java:97)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.startInternal(Tool.java:262)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.start(Tool.java:225)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.JMap.main(JMap.java:176)
	at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.runJMAP(SALauncher.java:331)
	at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:483)

Only one failure so far. This test is spent most of it's life on the problem list due to multiple issues which have been addressed recently, thus its removal from the problem list. I didn't see it fail in this manner after rigorous testing, so I'm guessing it is very rare.

Based on the stack trace, it looks like this may be similar in a way to the NPE we got in JDK-8243210. The problem is that if you try to create an Address object for address 0, you get a null back rather than an Address object that references address 0. Parts of SA, and the heap walkers are one, need to be able to deal with possibly invalid addresses, so normally some sanity check is done on the address, and part of the sanity check needs to be to check for a null Address. There might be a missing null check here.

I should also add this this bug is likely instigated by the fact that the target is actively mutating, thus increasing the likelihood of the heap being in a state where it cannot be 100% safely walked, but like I said, SA is suppose to deal with this by doing address validation.
Comments
URL: https://hg.openjdk.java.net/jdk/jdk/rev/b980b0247350 User: cjplummer Date: 2020-05-22 20:31:55 +0000
22-05-2020

There is another variant of this bug that is not covered by having ClassLoaderDataGraph.classesDo() filter classes that have not yet reached the "loaded" state: java.lang.NullPointerException at jdk.hotspot.agent/sun.jvm.hotspot.oops.InstanceKlass.getAllFieldsCount(InstanceKlass.java:410) at jdk.hotspot.agent/sun.jvm.hotspot.oops.InstanceKlass.<init>(InstanceKlass.java:148) at jdk.internal.reflect.GeneratedConstructorAccessor3.newInstance(Unknown Source) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481) at jdk.hotspot.agent/sun.jvm.hotspot.runtime.VMObjectFactory.newObject(VMObjectFactory.java:58) at jdk.hotspot.agent/sun.jvm.hotspot.runtime.VirtualBaseConstructor.instantiateWrapperFor(VirtualBaseConstructor.java:106) at jdk.hotspot.agent/sun.jvm.hotspot.oops.Metadata.instantiateWrapperFor(Metadata.java:76) at jdk.hotspot.agent/sun.jvm.hotspot.oops.MetadataField.getValue(MetadataField.java:43) at jdk.hotspot.agent/sun.jvm.hotspot.oops.MetadataField.getValue(MetadataField.java:40) at jdk.hotspot.agent/sun.jvm.hotspot.classfile.ClassLoaderData.getKlasses(ClassLoaderData.java:89) at jdk.hotspot.agent/sun.jvm.hotspot.classfile.ClassLoaderData.classesDo(ClassLoaderData.java:104) at jdk.hotspot.agent/sun.jvm.hotspot.classfile.ClassLoaderDataGraph.classesDo(ClassLoaderDataGraph.java:84) at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.writeSymbols(HeapHprofBinWriter.java:1166) at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.write(HeapHprofBinWriter.java:439) at jdk.hotspot.agent/sun.jvm.hotspot.tools.JMap.writeHeapHprofBin(JMap.java:182) at jdk.hotspot.agent/sun.jvm.hotspot.tools.JMap.run(JMap.java:97) at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.startInternal(Tool.java:262) at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.start(Tool.java:225) at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.execute(Tool.java:118) at jdk.hotspot.agent/sun.jvm.hotspot.tools.JMap.main(JMap.java:176) at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.runJMAP(SALauncher.java:331) at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:483) In this case ClassLoaderData.classesDo() is trying to get the first Klass in the ClassLoaderData::_klasses list. This requires instantiating the wrapper for the Klass. In this case it is an InstanceKlass that is still so early on in the loading phase that it has been registered with the ClassLoaderData, but does not yet have InstanceKlass::_fields initialized. Since it is null, that is what gets copied into the wrapper, and then causes an NPE when deferenced. The window for this bug is pretty small.In classFileParser.cpp we have: _loader_data->add_class(ik, publicize); Which adds the Klass to ClassLoaderData::_klasses (making it first in the list). At this point SA is vulnerable to this NPE, but only for a short time. A lines later we have: // this transfers ownership of a lot of arrays from // the parser onto the InstanceKlass* apply_parsed_class_metadata(ik, _java_fields_count, CHECK); And then within apply_parsed_class_metadata(): _cp->set_pool_holder(this_klass); this_klass->set_constants(_cp); this_klass->set_fields(_fields, java_fields_count); One _fields is set, the NPE will no longer happen. So the window is pretty small, although somewhat bigger in debug buidls. The fix is to have InstanceKlass.<init>() not bother with _fields related initialization if InstanceKlass.isLoaded() returns false. We may need checks elsewhere that try to access _fields to make sure we just don't push the NPE off to some other unexpected code.
19-05-2020

The issues is that while using ClassLoaderDataGraph.classesDo() to iterate over all Klass instances, SA stumbles across one that is in the process of being loaded. Its init_stated is still 0, which means "allocated", but the InstanceKlass has no java mirror yet (an instance of java.lang.Class). The npe is because the null java mirror is passed to writeField(), which passes it to Field.getValue, which tries to deference it. Although we could special case the code in writeClassDumpRecord() or writeFieldDescriptors() to detect the null java mirror and not attempt to write any fields in that case, I think the best approach is to change ClassLoaderDataGraph.classesDo() to skip over classes that are not at least loaded to the point to having a java mirror. Checking InstanceKlass.isLoaded() will accomplish this. This result in some parts of SA that don't need the java mirror no longer to being able to display information about a class that is currently being loaded, but I don't think this will affect anyone's debugging experience. It's not really information that should ever be needed.
06-05-2020

There have been two more failures. Look to be the same except the topmost frame is different. This is just because the field type is different: java.lang.NullPointerException at jdk.hotspot.agent/sun.jvm.hotspot.oops.LongField.getValue(LongField.java:44) at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.writeField(HeapHprofBinWriter.java:1031) at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.writeFieldDescriptors(HeapHprofBinWriter.java:981) at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.writeClassDumpRecord(HeapHprofBinWriter.java:663) at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter$1.visit(HeapHprofBinWriter.java:600) at jdk.hotspot.agent/sun.jvm.hotspot.classfile.ClassLoaderData.classesDo(ClassLoaderData.java:105) at jdk.hotspot.agent/sun.jvm.hotspot.classfile.ClassLoaderDataGraph.classesDo(ClassLoaderDataGraph.java:84) at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.writeClassDumpRecords(HeapHprofBinWriter.java:596) at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.write(HeapHprofBinWriter.java:442) at jdk.hotspot.agent/sun.jvm.hotspot.tools.JMap.writeHeapHprofBin(JMap.java:182) at jdk.hotspot.agent/sun.jvm.hotspot.tools.JMap.run(JMap.java:97) at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.startInternal(Tool.java:262) at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.start(Tool.java:225) at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.execute(Tool.java:118) at jdk.hotspot.agent/sun.jvm.hotspot.tools.JMap.main(JMap.java:176) at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.runJMAP(SALauncher.java:331) at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:483)
05-05-2020