JDK-8231287 : "jhsdb jmap" should do a better job of reporting exception it catches
  • Type: Sub-task
  • Component: hotspot
  • Sub-Component: svc-agent
  • Affected Version: 14
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2019-09-20
  • Updated: 2020-11-03
  • Resolved: 2019-09-30
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 14
14 b17Fixed
Related Reports
Relates :  
Description
When running JShellHeapDumpTest, you sometimes see an EOFException failure. Just before the exception you'll see "null" or "illegal bci". These are being printed out by the following in JMap.java:

    public boolean writeHeapHprofBin(String fileName) {
        try {
            HeapGraphWriter hgw = new HeapHprofBinWriter();
            hgw.write(fileName);
            System.out.println("heap written to " + fileName);
            return true;
        } catch (IOException | RuntimeException exp) {
            System.err.println(exp.getMessage()); <-----------
            return false;
        }
    }

The "null" is because the exception has no message, and this is what String.valueOf(obj) returns in that case. The "illegal bci" is the message from an AssertionFailure exception that is being caught here. I think this code should be changed to the following to there is more reasonable detail in the output:

            exp.printStackTrace(System.err);

Once this is done, you see a better explanation for the failures:

sun.jvm.hotspot.utilities.AssertionFailure: illegal bci
at jdk.hotspot.agent/sun.jvm.hotspot.utilities.Assert.that(Assert.java:32)
at jdk.hotspot.agent/sun.jvm.hotspot.oops.ConstMethod.getLineNumberFromBCI(ConstMethod.java:297)
at jdk.hotspot.agent/sun.jvm.hotspot.oops.Method.getLineNumberFromBCI(Method.java:282)
at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.dumpStackFrame(HeapHprofBinWriter.java:751)
at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.dumpStackTraces(HeapHprofBinWriter.java:730)
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:260)
at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.start(Tool.java:223)
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:321)
at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:406)

sun.jvm.hotspot.utilities.AssertionFailure: must be a valid non-zero index
at jdk.hotspot.agent/sun.jvm.hotspot.utilities.Assert.that(Assert.java:32)
at jdk.hotspot.agent/sun.jvm.hotspot.code.NMethod.getMetadataAt(NMethod.java:200)
at jdk.hotspot.agent/sun.jvm.hotspot.code.NMethod.getMethodAt(NMethod.java:206)
at jdk.hotspot.agent/sun.jvm.hotspot.code.DebugInfoReadStream.readMethod(DebugInfoReadStream.java:58)
at jdk.hotspot.agent/sun.jvm.hotspot.code.ScopeDesc.<init>(ScopeDesc.java:64)
at jdk.hotspot.agent/sun.jvm.hotspot.code.ScopeDesc.sender(ScopeDesc.java:121)
at jdk.hotspot.agent/sun.jvm.hotspot.runtime.CompiledVFrame.sender(CompiledVFrame.java:187)
at jdk.hotspot.agent/sun.jvm.hotspot.runtime.VFrame.javaSender(VFrame.java:143)
at jdk.hotspot.agent/sun.jvm.hotspot.runtime.ThreadStackTrace.dumpStack(ThreadStackTrace.java:54)
at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.dumpStackTraces(HeapHprofBinWriter.java:718)
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:260)
at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.start(Tool.java:223)
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:321)
at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:406)

And this is the one for the "null" message:

java.lang.NullPointerException
at jdk.hotspot.agent/sun.jvm.hotspot.utilities.HeapHprofBinWriter.dumpStackTraces(HeapHprofBinWriter.java:727)
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:260)
at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.start(Tool.java:223)
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:321)
at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:406) 
Comments
URL: https://hg.openjdk.java.net/jdk/jdk/rev/31524b016783 User: cjplummer Date: 2019-09-28 19:35:16 +0000
30-09-2019

On further inspection, catching and not re-throwing these exceptions is probably itself also a bug. If the exception is not caught, or is re-thrown, you get the desired result of the tool exiting with exitcode 1. This is the code that will see the exception in Tool.java: protected void execute(String[] args) { int returnStatus = 1; try { returnStatus = start(args); } finally { stop(); } // Exit with 0 or 1 System.exit(returnStatus); } Propagating the exception to Tool.execute() allows jtreg tests to properly fail the output.shouldHaveExitValue(0) check when an exception is thrown, rather than having to check for some unknown exception message in the jmap output, or worse yet, not even noticing the exception, and instead fail to read the missing or incomplete hprof file. Catching the IOException has always been there, and is because hgw.write(fileName) declares that it throws it. However, I think it's a bug that it does not re-throw some sort of exception when catching IOException. Catching the RuntimeException is relatively new and unnecessary. It got added as part of the fix for JDK-8213323. I think it was the following in the review process that led to it's addition: http://mail.openjdk.java.net/pipermail/serviceability-dev/2018-November/025884.html However, just because a RuntimeException can now be thrown does not mean that it needs to be caught. You can remove the catch of this exception and the code still compiles. I think the proper fix is to no longer catch RuntimeException, re-throw the IOException as a RuntimeException, and to have tool.execute() catch and print all exceptions.
27-09-2019