8201556: Disallow reading oops in ClassLoaderData if unloading
authorcoleenp
Wed, 18 Apr 2018 18:43:04 -0400
changeset 49824 e242740a92b8
parent 49823 af4b57a556be
child 49825 f909f09569ca
8201556: Disallow reading oops in ClassLoaderData if unloading Summary: Move class_loader oop to an OopHandle, and assert that holder is alive when getting class_loader. Reviewed-by: kbarrett, adinn
src/hotspot/share/classfile/classLoaderData.cpp
src/hotspot/share/classfile/classLoaderData.hpp
src/hotspot/share/classfile/classLoaderData.inline.hpp
src/hotspot/share/classfile/classLoaderStats.cpp
src/hotspot/share/classfile/moduleEntry.cpp
src/hotspot/share/classfile/placeholders.cpp
src/hotspot/share/classfile/systemDictionaryShared.cpp
src/hotspot/share/classfile/systemDictionaryShared.hpp
src/hotspot/share/gc/g1/g1MonitoringSupport.cpp
src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp
src/hotspot/share/gc/shared/genCollectedHeap.cpp
src/hotspot/share/memory/heapInspection.cpp
src/hotspot/share/memory/universe.cpp
src/hotspot/share/oops/instanceKlass.cpp
src/hotspot/share/oops/klass.cpp
src/hotspot/share/oops/oopHandle.hpp
src/hotspot/share/oops/weakHandle.cpp
src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp
src/hotspot/share/runtime/vmStructs.cpp
src/hotspot/share/services/classLoadingService.cpp
src/hotspot/share/trace/traceStream.cpp
src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java
--- a/src/hotspot/share/classfile/classLoaderData.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -54,6 +54,7 @@
 #include "classfile/metadataOnStackMark.hpp"
 #include "classfile/moduleEntry.hpp"
 #include "classfile/packageEntry.hpp"
+#include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
@@ -102,8 +103,25 @@
   }
 }
 
+// JFR and logging support so that the name and klass are available after the
+// class_loader oop is no longer alive, during unloading.
+void ClassLoaderData::initialize_name_and_klass(Handle class_loader) {
+  _class_loader_klass = class_loader->klass();
+  oop class_loader_name = java_lang_ClassLoader::name(class_loader());
+  if (class_loader_name != NULL) {
+    Thread* THREAD = Thread::current();
+    ResourceMark rm(THREAD);
+    const char* class_loader_instance_name =
+      java_lang_String::as_utf8_string(class_loader_name);
+
+    if (class_loader_instance_name != NULL && class_loader_instance_name[0] != '\0') {
+      // Can't throw InternalError and SymbolTable doesn't throw OOM anymore.
+      _class_loader_name = SymbolTable::new_symbol(class_loader_instance_name, CATCH);
+    }
+  }
+}
+
 ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous) :
-  _class_loader(h_class_loader()),
   _is_anonymous(is_anonymous),
   // An anonymous class loader data doesn't have anything to keep
   // it from being unloaded during parsing of the anonymous class.
@@ -114,9 +132,14 @@
   _claimed(0), _modified_oops(true), _accumulated_modified_oops(false),
   _jmethod_ids(NULL), _handles(), _deallocate_list(NULL),
   _next(NULL),
+  _class_loader_klass(NULL), _class_loader_name(NULL),
   _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
                             Monitor::_safepoint_check_never)) {
 
+  if (!h_class_loader.is_null()) {
+    _class_loader = _handles.add(h_class_loader());
+  }
+
   if (!is_anonymous) {
     // The holder is initialized later for anonymous classes, and before calling anything
     // that call class_loader().
@@ -269,7 +292,6 @@
     clear_modified_oops();
   }
 
-  f->do_oop(&_class_loader);
   _handles.oops_do(f);
 }
 
@@ -556,7 +578,7 @@
   if (lt.is_enabled()) {
     ResourceMark rm;
     LogStream ls(lt);
-    ls.print("unload ");
+    ls.print("unload");
     print_value_on(&ls);
     ls.cr();
   }
@@ -631,7 +653,7 @@
 // Unloading support
 bool ClassLoaderData::is_alive() const {
   bool alive = keep_alive()         // null class loader and incomplete anonymous klasses.
-      || (_holder.peek() != NULL);  // not cleaned by weak reference processing
+      || (_holder.peek() != NULL);  // and not cleaned by the GC weak handle processing.
 
   return alive;
 }
@@ -887,13 +909,23 @@
 }
 
 const char* ClassLoaderData::loader_name() const {
-  // Handles null class loader
-  return SystemDictionary::loader_name(class_loader());
+  if (is_unloading()) {
+    if (_class_loader_klass == NULL) {
+      return "<bootloader>";
+    } else if (_class_loader_name != NULL) {
+      return _class_loader_name->as_C_string();
+    } else {
+      return _class_loader_klass->name()->as_C_string();
+    }
+  } else {
+    // Handles null class loader
+    return SystemDictionary::loader_name(class_loader());
+  }
 }
 
 
 void ClassLoaderData::print_value_on(outputStream* out) const {
-  if (class_loader() != NULL) {
+  if (!is_unloading() && class_loader() != NULL) {
     out->print("loader data: " INTPTR_FORMAT " for instance ", p2i(this));
     class_loader()->print_value_on(out);  // includes loader_name() and address of class loader instance
   } else {
@@ -908,7 +940,7 @@
 #ifndef PRODUCT
 void ClassLoaderData::print_on(outputStream* out) const {
   out->print("ClassLoaderData CLD: " PTR_FORMAT ", loader: " PTR_FORMAT ", loader_klass: %s {",
-              p2i(this), p2i((void *)class_loader()), loader_name());
+              p2i(this), p2i(_class_loader.ptr_raw()), loader_name());
   if (is_anonymous()) out->print(" anonymous");
   if (claimed()) out->print(" claimed");
   if (is_unloading()) out->print(" unloading");
@@ -962,10 +994,10 @@
 
 // Add a new class loader data node to the list.  Assign the newly created
 // ClassLoaderData into the java/lang/ClassLoader object as a hidden field
-ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_anonymous) {
+ClassLoaderData* ClassLoaderDataGraph::add_to_graph(Handle loader, bool is_anonymous) {
   NoSafepointVerifier no_safepoints; // we mustn't GC until we've installed the
                                      // ClassLoaderData in the graph since the CLD
-                                     // contains unhandled oops
+                                     // contains oops in _handles that must be walked.
 
   ClassLoaderData* cld = new ClassLoaderData(loader, is_anonymous);
 
@@ -1002,6 +1034,16 @@
   } while (true);
 }
 
+ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_anonymous) {
+  ClassLoaderData* loader_data = add_to_graph(loader, is_anonymous);
+  // Initialize name and class after the loader data is added to the CLDG
+  // because adding the Symbol for the name might safepoint.
+  if (loader.not_null()) {
+    loader_data->initialize_name_and_klass(loader);
+  }
+  return loader_data;
+}
+
 void ClassLoaderDataGraph::oops_do(OopClosure* f, bool must_claim) {
   for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
     cld->oops_do(f, must_claim);
--- a/src/hotspot/share/classfile/classLoaderData.hpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.hpp	Wed Apr 18 18:43:04 2018 -0400
@@ -28,7 +28,6 @@
 #include "memory/allocation.hpp"
 #include "memory/memRegion.hpp"
 #include "memory/metaspace.hpp"
-#include "memory/metaspaceCounters.hpp"
 #include "oops/oopHandle.hpp"
 #include "oops/weakHandle.hpp"
 #include "runtime/mutex.hpp"
@@ -84,6 +83,7 @@
   static volatile size_t  _num_instance_classes;
   static volatile size_t  _num_array_classes;
 
+  static ClassLoaderData* add_to_graph(Handle class_loader, bool anonymous);
   static ClassLoaderData* add(Handle class_loader, bool anonymous);
   static void post_class_unload_events();
  public:
@@ -220,8 +220,8 @@
 
   static ClassLoaderData * _the_null_class_loader_data;
 
-  ClassLoaderWeakHandle _holder; // The oop that determines lifetime of this class loader
-  oop _class_loader;          // The instance of java/lang/ClassLoader associated with
+  WeakHandle<vm_class_loader_data> _holder; // The oop that determines lifetime of this class loader
+  OopHandle _class_loader;    // The instance of java/lang/ClassLoader associated with
                               // this ClassLoaderData
 
   ClassLoaderMetaspace * volatile _metaspace;  // Meta-space where meta-data defined by the
@@ -234,7 +234,7 @@
   bool _modified_oops;             // Card Table Equivalent (YC/CMS support)
   bool _accumulated_modified_oops; // Mod Union Equivalent (CMS support)
 
-  s2 _keep_alive;          // if this CLD is kept alive without a keep_alive_object().
+  s2 _keep_alive;          // if this CLD is kept alive.
                            // Used for anonymous classes and the boot class
                            // loader. _keep_alive does not need to be volatile or
                            // atomic since there is one unique CLD per anonymous class.
@@ -265,6 +265,9 @@
   // Support for walking class loader data objects
   ClassLoaderData* _next; /// Next loader_datas created
 
+  // JFR support
+  Klass*  _class_loader_klass;
+  Symbol* _class_loader_name;
   TRACE_DEFINE_TRACE_ID_FIELD;
 
   void set_next(ClassLoaderData* next) { _next = next; }
@@ -305,6 +308,8 @@
   MetaWord* allocate(size_t size);
 
   Dictionary* create_dictionary();
+
+  void initialize_name_and_klass(Handle class_loader);
  public:
   // GC interface.
   void clear_claimed() { _claimed = 0; }
@@ -340,9 +345,7 @@
 
   // Returns true if this class loader data is for the boot class loader.
   // (Note that the class loader data may be anonymous.)
-  bool is_boot_class_loader_data() const {
-    return class_loader() == NULL;
-  }
+  inline bool is_boot_class_loader_data() const;
 
   bool is_builtin_class_loader_data() const;
   bool is_permanent_class_loader_data() const;
@@ -351,10 +354,7 @@
   // method will allocate a Metaspace if needed.
   ClassLoaderMetaspace* metaspace_non_null();
 
-  oop class_loader() const { return _class_loader; }
-
-  // The object the GC is using to keep this ClassLoaderData alive.
-  oop keep_alive_object() const;
+  inline oop class_loader() const;
 
   // Returns true if this class loader data is for a loader going away.
   bool is_unloading() const     {
@@ -363,7 +363,7 @@
   }
 
   // Used to refcount an anonymous class's CLD in order to
-  // indicate their aliveness without a keep_alive_object().
+  // indicate their aliveness.
   void inc_keep_alive();
   void dec_keep_alive();
 
@@ -407,6 +407,9 @@
   static ClassLoaderData* class_loader_data_or_null(oop loader);
   static ClassLoaderData* anonymous_class_loader_data(Handle loader);
 
+
+  Klass* class_loader_klass() const { return _class_loader_klass; }
+  Symbol* class_loader_name() const { return _class_loader_name; }
   TRACE_DEFINE_TRACE_ID_METHODS;
 };
 
--- a/src/hotspot/share/classfile/classLoaderData.inline.hpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.inline.hpp	Wed Apr 18 18:43:04 2018 -0400
@@ -28,6 +28,18 @@
 #include "classfile/classLoaderData.hpp"
 #include "classfile/javaClasses.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/oopHandle.inline.hpp"
+#include "oops/weakHandle.inline.hpp"
+
+inline oop ClassLoaderData::class_loader() const {
+  assert(!_unloading, "This oop is not available to unloading class loader data");
+  assert(_holder.is_null() || _holder.peek() != NULL , "This class loader data holder must be alive");
+  return _class_loader.resolve();
+}
+
+inline bool ClassLoaderData::is_boot_class_loader_data() const {
+    return class_loader() == NULL;
+  }
 
 inline ClassLoaderData* ClassLoaderData::class_loader_data_or_null(oop loader) {
   if (loader == NULL) {
--- a/src/hotspot/share/classfile/classLoaderStats.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderStats.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/classLoaderStats.hpp"
 #include "oops/oop.inline.hpp"
 #include "utilities/globalDefinitions.hpp"
--- a/src/hotspot/share/classfile/moduleEntry.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/moduleEntry.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -24,7 +24,7 @@
 
 #include "precompiled.hpp"
 #include "jni.h"
-#include "classfile/classLoaderData.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/moduleEntry.hpp"
 #include "logging/log.hpp"
--- a/src/hotspot/share/classfile/placeholders.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/placeholders.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/placeholders.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "oops/oop.inline.hpp"
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -357,6 +357,14 @@
   return pd;
 }
 
+bool SystemDictionaryShared::is_sharing_possible(ClassLoaderData* loader_data) {
+  oop class_loader = loader_data->class_loader();
+  return (class_loader == NULL ||
+          (UseAppCDS && (SystemDictionary::is_system_class_loader(class_loader) ||
+                         SystemDictionary::is_platform_class_loader(class_loader)))
+          );
+}
+
 // Currently AppCDS only archives classes from the run-time image, the
 // -Xbootclasspath/a path, the class path, and the module path.
 //
--- a/src/hotspot/share/classfile/systemDictionaryShared.hpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp	Wed Apr 18 18:43:04 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -300,13 +300,7 @@
   }
 
   // Check if sharing is supported for the class loader.
-  static bool is_sharing_possible(ClassLoaderData* loader_data) {
-    oop class_loader = loader_data->class_loader();
-    return (class_loader == NULL ||
-            (UseAppCDS && (SystemDictionary::is_system_class_loader(class_loader) ||
-                           SystemDictionary::is_platform_class_loader(class_loader)))
-            );
-  }
+  static bool is_sharing_possible(ClassLoaderData* loader_data);
   static bool is_shared_class_visible_for_classloader(InstanceKlass* ik,
                                                       Handle class_loader,
                                                       const char* pkg_string,
--- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -27,6 +27,7 @@
 #include "gc/g1/g1MonitoringSupport.hpp"
 #include "gc/g1/g1Policy.hpp"
 #include "gc/shared/hSpaceCounters.hpp"
+#include "memory/metaspaceCounters.hpp"
 
 G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm,
                                            const char* name,
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -41,6 +41,7 @@
 #include "gc/shared/gcLocker.hpp"
 #include "gc/shared/gcWhen.hpp"
 #include "logging/log.hpp"
+#include "memory/metaspaceCounters.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/java.hpp"
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -49,6 +49,7 @@
 #include "gc/shared/weakProcessor.hpp"
 #include "gc/shared/workgroup.hpp"
 #include "memory/filemap.hpp"
+#include "memory/metaspaceCounters.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/biasedLocking.hpp"
--- a/src/hotspot/share/memory/heapInspection.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/memory/heapInspection.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
  */
 
 #include "precompiled.hpp"
-#include "classfile/classLoaderData.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/moduleEntry.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "gc/shared/collectedHeap.hpp"
--- a/src/hotspot/share/memory/universe.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/memory/universe.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -46,6 +46,7 @@
 #include "memory/filemap.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspaceClosure.hpp"
+#include "memory/metaspaceCounters.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
--- a/src/hotspot/share/oops/instanceKlass.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -28,6 +28,7 @@
 #include "classfile/classFileParser.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/moduleEntry.hpp"
 #include "classfile/systemDictionary.hpp"
--- a/src/hotspot/share/oops/klass.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/oops/klass.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/dictionary.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/systemDictionary.hpp"
--- a/src/hotspot/share/oops/oopHandle.hpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/oops/oopHandle.hpp	Wed Apr 18 18:43:04 2018 -0400
@@ -46,7 +46,7 @@
   inline oop resolve() const;
 
   // Used only for removing handle.
-  oop* ptr_raw() { return _obj; }
+  oop* ptr_raw() const { return _obj; }
 };
 
 #endif // SHARE_VM_OOPS_OOPHANDLE_HPP
--- a/src/hotspot/share/oops/weakHandle.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/oops/weakHandle.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -51,8 +51,8 @@
 void WeakHandle<T>::release() const {
   // Only release if the pointer to the object has been created.
   if (_obj != NULL) {
-    // Clear the WeakHandle.  For class loader data race, the handle may not have
-    // been previously cleared by GC.
+    // Clear the WeakHandle.  For race in creating ClassLoaderData, we can release this
+    // WeakHandle before it is cleared by GC.
     RootAccess<ON_PHANTOM_OOP_REF>::oop_store(_obj, (oop)NULL);
     get_storage()->release(_obj);
   }
--- a/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiGetLoadedClasses.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "memory/universe.hpp"
--- a/src/hotspot/share/runtime/vmStructs.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/runtime/vmStructs.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -543,7 +543,7 @@
   /*******************/                                                                                                              \
   /* ClassLoaderData */                                                                                                              \
   /*******************/                                                                                                              \
-  nonstatic_field(ClassLoaderData,             _class_loader,                                 oop)                                   \
+  nonstatic_field(ClassLoaderData,             _class_loader,                                 OopHandle)                             \
   nonstatic_field(ClassLoaderData,             _next,                                         ClassLoaderData*)                      \
   volatile_nonstatic_field(ClassLoaderData,    _klasses,                                      Klass*)                                \
   nonstatic_field(ClassLoaderData,             _is_anonymous,                                 bool)                                  \
--- a/src/hotspot/share/services/classLoadingService.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/services/classLoadingService.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,7 @@
       len = name->utf8_length();                    \
     }                                               \
     HOTSPOT_CLASS_##type( /* type = unloaded, loaded */ \
-      data, len, (void*)(clss)->class_loader(), (shared)); \
+      data, len, (void*)(clss)->class_loader_data(), (shared)); \
   }
 
 #else //  ndef DTRACE_ENABLED
--- a/src/hotspot/share/trace/traceStream.cpp	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/hotspot/share/trace/traceStream.cpp	Wed Apr 18 18:43:04 2018 -0400
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
 #include "precompiled.hpp"
 #include "trace/traceStream.hpp"
 #if INCLUDE_TRACE
-#include "classfile/classLoaderData.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/javaClasses.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/klass.hpp"
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java	Wed Apr 18 10:30:57 2018 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java	Wed Apr 18 18:43:04 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,14 +42,14 @@
 
   private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
     Type type      = db.lookupType("ClassLoaderData");
-    classLoaderField = type.getOopField("_class_loader");
+    classLoaderField = type.getAddressField("_class_loader");
     nextField = type.getAddressField("_next");
     klassesField = new MetadataField(type.getAddressField("_klasses"), 0);
     isAnonymousField = new CIntField(type.getCIntegerField("_is_anonymous"), 0);
     dictionaryField = type.getAddressField("_dictionary");
   }
 
-  private static sun.jvm.hotspot.types.OopField classLoaderField;
+  private static AddressField   classLoaderField;
   private static AddressField nextField;
   private static MetadataField  klassesField;
   private static CIntField isAnonymousField;
@@ -72,7 +72,13 @@
   }
 
   public Oop getClassLoader() {
-    return VM.getVM().getObjectHeap().newOop(classLoaderField.getValue(getAddress()));
+    Address handle = classLoaderField.getValue(getAddress());
+    if (handle != null) {
+      // Load through the handle
+      OopHandle refs = handle.getOopHandleAt(0);
+      return (Instance)VM.getVM().getObjectHeap().newOop(refs);
+    }
+    return null;
   }
 
   public boolean getIsAnonymous() {