JDK-8031376 : TraceClassLoading expects there to be a (Java) caller when you load a class with the bootstrap class loader
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 9
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2014-01-08
  • Updated: 2015-01-21
  • Resolved: 2014-01-08
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 8 JDK 9
8u40Fixed 9 b03Fixed
Description
From: Jeremy Manson <jeremymanson@google.com>
Subject: Crash with TraceClassLoading
Date: 19 december 2013 21:01:02 CET
To: "hotspot-runtime-dev@openjdk.java.net" <hotspot-runtime-dev@openjdk.java.net>

Now that 9 is underway, presumably we can start feeding back fixes again.

This one's a bit obscure.  TraceClassLoading expects there to be a (Java) caller when you load a class with the bootstrap class loader.  However, there are ways of loading a class that don't involve having a Java caller.  For example, you can do so from a JVMTI hook.  A reproduction is attached, and here's a patch:

diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp
--- a/src/share/vm/classfile/classFileParser.cpp
+++ b/src/share/vm/classfile/classFileParser.cpp
@@ -4098,8 +4098,12 @@
         tty->print("[Loaded %s from %s]\n", this_klass->external_name(),
                    cfs->source());
       } else if (class_loader.is_null()) {
-        if (THREAD->is_Java_thread()) {
-          Klass* caller = ((JavaThread*)THREAD)->security_get_caller_class(1);
+        Klass* caller =
+            THREAD->is_Java_thread()
+                ? ((JavaThread*)THREAD)->security_get_caller_class(1)
+                : NULL;
+        // caller can be NULL, for example, during a JVMTI VM_Init hook
+        if (caller != NULL) {
           tty->print("[Loaded %s by instance of %s]\n",
                      this_klass->external_name(),
                      InstanceKlass::cast(caller)->external_name());

Jeremy