JDK-8175341 : "java/util/Arrays/ParallelPrefix.java" Crash Internal Error ...diagnosticCommand.cpp...assert(k != __null) failed: FinalizerHistogram class is not accessible
  • Type: Bug
  • Component: hotspot
  • Sub-Component: svc
  • Affected Version: 9,10
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2017-02-21
  • Updated: 2017-08-25
  • Resolved: 2017-03-07
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 10
10 b21Fixed
Related Reports
Relates :  
Description
I got the following during an RBT run on a clean JDK 10:

 "java/util/Arrays/ParallelPrefix.java" Crash Internal Error ...diagnosticCommand.cpp...assert(k != __null) failed: FinalizerHistogram class is not accessible 

#  Internal Error (/scratch/opt/jprt/T/P1/210316.cplummer/s/hotspot/src/share/vm/services/diagnosticCommand.cpp:426), pid=9329, tid=14803
#  assert(k != __null) failed: FinalizerHistogram class is not accessible

This is probably related to the OOME mentioned for this test in JDK-8085982.
Comments
Ok, so resolve_or_null() doesn't throw an exception, so we don't hit the exception handling code in jcmd(). Changing it to resolve_or_fail() does result in the exception pending, and you do see the exception printed by jcmd(). The following gets rid of the assert and makes sure the exception is printed: - Klass* k = SystemDictionary::resolve_or_null( - vmSymbols::finalizer_histogram_klass(), THREAD); - assert(k != NULL, "FinalizerHistogram class is not accessible"); + Klass* k = SystemDictionary::resolve_or_fail( + vmSymbols::finalizer_histogram_klass(), true, CHECK); I see the following in the serviceability/dcmd/gc/FinalizerInfoTest.java logfile if I remove the last character from the name of the FinalizerHistogram class (forcing a NoClassDefFoundError): stderr: [java.lang.NoClassDefFoundError: java/lang/ref/FinalizerHistogra ]
07-03-2017

The code is using resolve_or_null instead of resolve_or_fail. It should use resolve_or_fail and throw the exception.
07-03-2017

Hmm. Maybe I'm looking in the wrong place. I did force the class to fail to load by misnaming it. I see the "FinalizerHistogram class is not accessible" message in the output, but don't see any mention of the exception, which I expected to see because of the following: static jint jcmd(AttachOperation* op, outputStream* out) { Thread* THREAD = Thread::current(); // All the supplied jcmd arguments are stored as a single // string (op->arg(0)). This is parsed by the Dcmd framework. DCmd::parse_and_execute(DCmd_Source_AttachAPI, out, op->arg(0), ' ', THREAD); if (HAS_PENDING_EXCEPTION) { java_lang_Throwable::print(PENDING_EXCEPTION, out); out->cr(); CLEAR_PENDING_EXCEPTION; return JNI_ERR; } return JNI_OK; }
07-03-2017

Oh wait, my forced failure did not have an exception. I just tested by checking k != NULL rather than k == NULL. I'll see if I can throw an exception at that point and see how it gets handled. Actually, I'll just misname the class so it throws an exception when it fails to find it. That should pretty closely mimic what happens when there's an OOME.
07-03-2017

I think the error message is appropriate since the dcmd did not do its job. As for the exception, it looks like it simply goes unhandled. I did not see any additional error messages (after the converted assert message) in the test log. I'll need to check if the dcmd infrastructure eats/clears the exception. If not, leaving it pending could possibly have a negative impact on a subsequent dcmd that does check for exceptions.
07-03-2017

I agree with the suggestion to remove the assert and return NULL. Any class load operation can fail and failure has to be anticipated. Not sure a printf is needed - I'd expect the error to be reported up the call chain. Also note that if k is null then there is an exception pending, whcih should also be detected and handled somewhere up the call chain.
07-03-2017

Due to JDK-8085982, the test is running out of memory and eventually times out. The testing tools that gather jvm process info after a timeout are then run. One of them issues the GC.finalizer_info dcmd. It asserts here because there is no memory to load the needed class: Klass* k = SystemDictionary::resolve_or_null( vmSymbols::finalizer_histogram_klass(), THREAD); assert(k != NULL, "FinalizerHistogram class is not accessible"); I think the solution is to simply change this to a printf and return when k == NULL. This failure doesn't seem to be reproducible (at least not easily). The test fails a lot due to JDK-8085982, but I've only seen this assert twice, so we'll need to take it on faith that this does the right thing should this situation ever come up again. serviceability/dcmd/gc/FinalizerInfoTest.java does test the GC.finalizer_info dcmd. If FinalizerHistogram should fail to load because of reproducible conditions (eg. it does not exist), then this test will catch it. I did force k = NULL for one test run, and the test did fail as expected.
07-03-2017

I've added "affects version" 9 since I just realized that this was also uncovered with some JDK 9 testing I was doing. However, I've also lowered it to a p3 since it only occurs under out of memory conditions and only when using a specific dcmd. No plan to fix for 9.
07-03-2017