8170672: Event-based tracing to support classloader instances
authormgronlun
Tue, 06 Dec 2016 22:49:17 +0100
changeset 42639 762117d57d05
parent 42638 793e65ba88aa
child 42640 09dba077f1e7
8170672: Event-based tracing to support classloader instances Reviewed-by: hseigel, egahlin
hotspot/src/share/vm/classfile/classFileParser.cpp
hotspot/src/share/vm/classfile/classLoaderData.cpp
hotspot/src/share/vm/classfile/classLoaderData.hpp
hotspot/src/share/vm/classfile/moduleEntry.cpp
hotspot/src/share/vm/classfile/packageEntry.cpp
hotspot/src/share/vm/classfile/systemDictionary.cpp
hotspot/src/share/vm/memory/metaspaceTracer.cpp
hotspot/src/share/vm/oops/arrayKlass.cpp
hotspot/src/share/vm/oops/klass.cpp
hotspot/src/share/vm/trace/traceMacros.hpp
hotspot/src/share/vm/trace/traceStream.hpp
hotspot/src/share/vm/trace/traceevents.xml
hotspot/src/share/vm/trace/tracetypes.xml
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Tue Dec 06 22:49:17 2016 +0100
@@ -5412,7 +5412,7 @@
     }
   }
 
-  TRACE_INIT_KLASS_ID(ik);
+  TRACE_INIT_ID(ik);
 
   // If we reach here, all is well.
   // Now remove the InstanceKlass* from the _klass_to_deallocate field
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp	Tue Dec 06 22:49:17 2016 +0100
@@ -97,7 +97,7 @@
   _next(NULL), _dependencies(dependencies), _shared_class_loader_id(-1),
   _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
                             Monitor::_safepoint_check_never)) {
-    // empty
+  TRACE_INIT_ID(this);
 }
 
 void ClassLoaderData::init_dependencies(TRAPS) {
@@ -167,9 +167,10 @@
 }
 
 void ClassLoaderData::classes_do(void f(Klass * const)) {
-  assert_locked_or_safepoint(_metaspace_lock);
-  for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
+  // Lock-free access requires load_ptr_acquire
+  for (Klass* k = load_ptr_acquire(&_klasses); k != NULL; k = k->next_link()) {
     f(k);
+    assert(k != k->next_link(), "no loops!");
   }
 }
 
@@ -812,6 +813,16 @@
   }
 }
 
+void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
+  // Only walk the head until any clds not purged from prior unloading
+  // (CMS doesn't purge right away).
+  for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
+    assert(cld->is_unloading(), "invariant");
+    cl->do_cld(cld);
+  }
+}
+
 void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
   for (ClassLoaderData* cld = _head;  cld != NULL; cld = cld->_next) {
     CLDClosure* closure = cld->keep_alive() ? strong : weak;
@@ -1042,7 +1053,7 @@
   }
 }
 
-void ClassLoaderDataGraph::post_class_unload_events(void) {
+void ClassLoaderDataGraph::post_class_unload_events() {
 #if INCLUDE_TRACE
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
   if (Tracing::enabled()) {
@@ -1191,9 +1202,7 @@
   EventClassUnload event(UNTIMED);
   event.set_endtime(_class_unload_time);
   event.set_unloadedClass(k);
-  oop defining_class_loader = k->class_loader();
-  event.set_definingClassLoader(defining_class_loader != NULL ?
-                                defining_class_loader->klass() : (Klass*)NULL);
+  event.set_definingClassLoader(k->class_loader_data());
   event.commit();
 }
 
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp	Tue Dec 06 22:49:17 2016 +0100
@@ -30,6 +30,7 @@
 #include "memory/metaspace.hpp"
 #include "memory/metaspaceCounters.hpp"
 #include "runtime/mutex.hpp"
+#include "trace/traceMacros.hpp"
 #include "utilities/growableArray.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_TRACE
@@ -78,7 +79,7 @@
   static bool _metaspace_oom;
 
   static ClassLoaderData* add(Handle class_loader, bool anonymous, TRAPS);
-  static void post_class_unload_events(void);
+  static void post_class_unload_events();
  public:
   static ClassLoaderData* find_or_create(Handle class_loader, TRAPS);
   static void purge();
@@ -89,6 +90,7 @@
   static void always_strong_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim);
   // cld do
   static void cld_do(CLDClosure* cl);
+  static void cld_unloading_do(CLDClosure* cl);
   static void roots_cld_do(CLDClosure* strong, CLDClosure* weak);
   static void keep_alive_cld_do(CLDClosure* cl);
   static void always_strong_cld_do(CLDClosure* cl);
@@ -210,6 +212,8 @@
   static Metaspace* _ro_metaspace;
   static Metaspace* _rw_metaspace;
 
+  TRACE_DEFINE_TRACE_ID_FIELD;
+
   void set_next(ClassLoaderData* next) { _next = next; }
   ClassLoaderData* next() const        { return _next; }
 
@@ -342,6 +346,8 @@
     assert(_shared_class_loader_id <0, "cannot be assigned more than once");
     _shared_class_loader_id = id;
   }
+
+  TRACE_DEFINE_TRACE_ID_METHODS;
 };
 
 // An iterator that distributes Klasses to parallel worker threads.
--- a/hotspot/src/share/vm/classfile/moduleEntry.cpp	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp	Tue Dec 06 22:49:17 2016 +0100
@@ -309,7 +309,7 @@
     }
   }
 
-  TRACE_INIT_MODULE_ID(entry);
+  TRACE_INIT_ID(entry);
 
   return entry;
 }
--- a/hotspot/src/share/vm/classfile/packageEntry.cpp	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/classfile/packageEntry.cpp	Tue Dec 06 22:49:17 2016 +0100
@@ -214,7 +214,7 @@
   entry->set_hash(hash);
   entry->set_literal(name);
 
-  TRACE_INIT_PACKAGE_ID(entry);
+  TRACE_INIT_ID(entry);
 
   // Initialize fields specific to a PackageEntry
   entry->init();
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Tue Dec 06 22:49:17 2016 +0100
@@ -621,35 +621,28 @@
   return (nh);
 }
 
-// utility function for class load event
 static void post_class_load_event(const Ticks& start_time,
                                   instanceKlassHandle k,
-                                  Handle initiating_loader) {
+                                  const ClassLoaderData* init_cld) {
 #if INCLUDE_TRACE
   EventClassLoad event(UNTIMED);
   if (event.should_commit()) {
     event.set_starttime(start_time);
     event.set_loadedClass(k());
-    oop defining_class_loader = k->class_loader();
-    event.set_definingClassLoader(defining_class_loader != NULL ?
-      defining_class_loader->klass() : (Klass*)NULL);
-    oop class_loader = initiating_loader.is_null() ? (oop)NULL : initiating_loader();
-    event.set_initiatingClassLoader(class_loader != NULL ?
-      class_loader->klass() : (Klass*)NULL);
+    event.set_definingClassLoader(k->class_loader_data());
+    event.set_initiatingClassLoader(init_cld);
     event.commit();
   }
 #endif // INCLUDE_TRACE
 }
 
-// utility function for class define event
-static void class_define_event(instanceKlassHandle k) {
+static void class_define_event(instanceKlassHandle k,
+                               const ClassLoaderData* def_cld) {
 #if INCLUDE_TRACE
-  EventClassDefine event(UNTIMED);
+  EventClassDefine event;
   if (event.should_commit()) {
     event.set_definedClass(k());
-    oop defining_class_loader = k->class_loader();
-    event.set_definingClassLoader(defining_class_loader != NULL ?
-      defining_class_loader->klass() : (Klass*)NULL);
+    event.set_definingClassLoader(def_cld);
     event.commit();
   }
 #endif // INCLUDE_TRACE
@@ -907,7 +900,7 @@
     return NULL;
   }
 
-  post_class_load_event(class_load_start_time, k, class_loader);
+  post_class_load_event(class_load_start_time, k, loader_data);
 
 #ifdef ASSERT
   {
@@ -1090,7 +1083,7 @@
         JvmtiExport::post_class_load((JavaThread *) THREAD, k());
     }
 
-    post_class_load_event(class_load_start_time, k, class_loader);
+    post_class_load_event(class_load_start_time, k, loader_data);
   }
   assert(host_klass != NULL || NULL == cp_patches,
          "cp_patches only found with host_klass");
@@ -1641,7 +1634,7 @@
       JvmtiExport::post_class_load((JavaThread *) THREAD, k());
 
   }
-  class_define_event(k);
+  class_define_event(k, loader_data);
 }
 
 // Support parallel classloading
--- a/hotspot/src/share/vm/memory/metaspaceTracer.cpp	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/memory/metaspaceTracer.cpp	Tue Dec 06 22:49:17 2016 +0100
@@ -62,18 +62,12 @@
                                                     Metaspace::MetadataType mdtype) const {
   E event;
   if (event.should_commit()) {
+    event.set_classLoader(cld);
     if (cld->is_anonymous()) {
-      event.set_classLoader(NULL);
       event.set_anonymousClassLoader(true);
     } else {
-      if (cld->is_the_null_class_loader_data()) {
-        event.set_classLoader((Klass*) NULL);
-      } else {
-        event.set_classLoader(cld->class_loader()->klass());
-      }
       event.set_anonymousClassLoader(false);
     }
-
     event.set_size(word_size * BytesPerWord);
     event.set_metadataType((u1) mdtype);
     event.set_metaspaceObjectType((u1) objtype);
--- a/hotspot/src/share/vm/oops/arrayKlass.cpp	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/oops/arrayKlass.cpp	Tue Dec 06 22:49:17 2016 +0100
@@ -90,7 +90,7 @@
     set_super(Universe::is_bootstrapping() ? (Klass*)NULL : SystemDictionary::Object_klass());
     set_layout_helper(Klass::_lh_neutral_value);
     set_is_cloneable(); // All arrays are considered to be cloneable (See JLS 20.1.5)
-    TRACE_INIT_KLASS_ID(this);
+    TRACE_INIT_ID(this);
 }
 
 
--- a/hotspot/src/share/vm/oops/klass.cpp	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/oops/klass.cpp	Tue Dec 06 22:49:17 2016 +0100
@@ -488,7 +488,7 @@
 
 void Klass::remove_unshareable_info() {
   assert (DumpSharedSpaces, "only called for DumpSharedSpaces");
-  TRACE_REMOVE_KLASS_ID(this);
+  TRACE_REMOVE_ID(this);
 
   set_subklass(NULL);
   set_next_sibling(NULL);
@@ -501,7 +501,7 @@
 }
 
 void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
-  TRACE_RESTORE_KLASS_ID(this);
+  TRACE_RESTORE_ID(this);
 
   // If an exception happened during CDS restore, some of these fields may already be
   // set.  We leave the class on the CLD list, even if incomplete so that we don't
--- a/hotspot/src/share/vm/trace/traceMacros.hpp	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/trace/traceMacros.hpp	Tue Dec 06 22:49:17 2016 +0100
@@ -31,13 +31,9 @@
 #define EVENT_THREAD_DESTRUCT(thread)
 #define TRACE_KLASS_CREATION(k, p, t)
 
-#define TRACE_INIT_KLASS_ID(k)
-#define TRACE_REMOVE_KLASS_ID(k)
-#define TRACE_RESTORE_KLASS_ID(k)
-
-#define TRACE_INIT_MODULE_ID(m)
-#define TRACE_INIT_PACKAGE_ID(p)
-#define TRACE_INIT_THREAD_ID(td)
+#define TRACE_INIT_ID(k)
+#define TRACE_REMOVE_ID(k)
+#define TRACE_RESTORE_ID(k)
 #define TRACE_DATA TraceThreadData
 
 #define THREAD_TRACE_ID(thread) ((traceid)thread->osthread()->thread_id())
--- a/hotspot/src/share/vm/trace/traceStream.hpp	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/trace/traceStream.hpp	Tue Dec 06 22:49:17 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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
@@ -27,6 +27,8 @@
 
 #include "utilities/macros.hpp"
 #if INCLUDE_TRACE
+#include "classfile/classLoaderData.hpp"
+#include "classfile/javaClasses.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/klass.hpp"
 #include "oops/method.hpp"
@@ -101,6 +103,33 @@
     _st.print("%s = %s", label, description);
   }
 
+  void print_val(const char* label, const ClassLoaderData* const cld) {
+    ResourceMark rm;
+    if (cld == NULL || cld->is_anonymous()) {
+      _st.print("%s = NULL", label);
+      return;
+    }
+    const oop class_loader_oop = cld->class_loader();
+    if (class_loader_oop == NULL) {
+      _st.print("%s = NULL", label);
+      return;
+    }
+    const char* class_loader_name = "NULL";
+    const char* klass_name = "NULL";
+    const oop class_loader_name_oop =
+      java_lang_ClassLoader::name(class_loader_oop);
+    if (class_loader_name_oop != NULL) {
+      class_loader_name =
+        java_lang_String::as_utf8_string(class_loader_name_oop);
+    }
+    const Klass* const k = class_loader_oop->klass();
+    const Symbol* klass_name_sym = k->name();
+    if (klass_name_sym != NULL) {
+      klass_name = klass_name_sym->as_C_string();
+    }
+    _st.print("%s = name=%s class=%s", label, class_loader_name, klass_name);
+  }
+
   void print_val(const char* label, const char* val) {
     _st.print("%s = '%s'", label, val);
   }
--- a/hotspot/src/share/vm/trace/traceevents.xml	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/trace/traceevents.xml	Tue Dec 06 22:49:17 2016 +0100
@@ -113,20 +113,20 @@
   <event id="ClassLoad" path="vm/class/load" label="Class Load"
          has_thread="true" has_stacktrace="true" is_instant="false">
     <value type="CLASS" field="loadedClass" label="Loaded Class"/>
-    <value type="CLASS" field="definingClassLoader" label="Defining Class Loader"/>
-    <value type="CLASS" field="initiatingClassLoader" label="Initiating Class Loader"/>
+    <value type="CLASSLOADER" field="definingClassLoader" label="Defining Class Loader"/>
+    <value type="CLASSLOADER" field="initiatingClassLoader" label="Initiating Class Loader"/>
   </event>
 
   <event id="ClassDefine" path="vm/class/define" label="Class Define"
          has_thread="true" has_stacktrace="true" is_instant="true">
     <value type="CLASS" field="definedClass" label="Defined Class"/>
-    <value type="CLASS" field="definingClassLoader" label="Defining Class Loader"/>
+    <value type="CLASSLOADER" field="definingClassLoader" label="Defining Class Loader"/>
   </event>
 
   <event id="ClassUnload" path="vm/class/unload" label="Class Unload"
          has_thread="true" is_instant="true">
     <value type="CLASS" field="unloadedClass" label="Unloaded Class"/>
-    <value type="CLASS" field="definingClassLoader" label="Defining Class Loader"/>
+    <value type="CLASSLOADER" field="definingClassLoader" label="Defining Class Loader"/>
   </event>
 
   <event id="IntFlagChanged" path="vm/flag/int_changed" label="Int Flag Changed"
@@ -229,7 +229,7 @@
   </event>
 
   <event id="MetaspaceAllocationFailure" path="vm/gc/metaspace/allocation_failure" label="Metaspace Allocation Failure" is_instant="true" has_stacktrace="true">
-    <value type="CLASS" field="classLoader" label="Class Loader" />
+    <value type="CLASSLOADER" field="classLoader" label="Class Loader" />
     <value type="BOOLEAN" field="anonymousClassLoader" label="Anonymous Class Loader" />
     <value type="BYTES64" field="size" label="Size" />
     <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
@@ -237,7 +237,7 @@
   </event>
 
   <event id="MetaspaceOOM" path="vm/gc/metaspace/out_of_memory" label="Metaspace Out of Memory" is_instant="true" has_stacktrace="true">
-    <value type="CLASS" field="classLoader" label="Class Loader" />
+    <value type="CLASSLOADER" field="classLoader" label="Class Loader" />
     <value type="BOOLEAN" field="anonymousClassLoader" label="Anonymous Class Loader" />
     <value type="BYTES64" field="size" label="Size" />
     <value type="METADATATYPE" field="metadataType" label="Metadata Type" />
--- a/hotspot/src/share/vm/trace/tracetypes.xml	Sat Dec 03 12:48:22 2016 +0300
+++ b/hotspot/src/share/vm/trace/tracetypes.xml	Tue Dec 06 22:49:17 2016 +0100
@@ -68,21 +68,27 @@
       <value type="THREADGROUP" field="group" label="Java Thread Group"/>
     </content_type>
 
-    <content_type id="ThreadGroup" hr_name="Thread group"
+    <content_type id="ThreadGroup" hr_name="Thread Group"
                   type="U8" jvm_type="THREADGROUP">
       <value type="THREADGROUP" field="parent" label="Parent"/>
       <value type="STRING" field="name" label="Name"/>
     </content_type>
 
-    <content_type id="Class" hr_name="Java class"
+    <content_type id="Class" hr_name="Java Class"
                   type="U8" builtin_type="CLASS">
-      <value type="CLASS" field="classLoaderType" label="Class Loader"/>
+      <value type="CLASSLOADER" field="classLoader" label="Class Loader"/>
       <value type="SYMBOL" field="name" label="Name"/>
       <value type="PACKAGE" field="package" label="Package"/>
       <value type="INTEGER" field="modifiers" label="Access Modifiers"/>
     </content_type>
 
-    <content_type id="Method" hr_name="Java method"
+    <content_type id="ClassLoader" hr_name="Java Class Loader"
+                  type="U8" jvm_type="CLASSLOADER">
+      <value type="CLASS" field="type" label="Type"/>
+      <value type="SYMBOL" field="name" label="Name"/>
+    </content_type>
+
+    <content_type id="Method" hr_name="Java Method"
                   type="U8" jvm_type="METHOD">
       <value type="CLASS" field="type" label="Type"/>
       <value type="SYMBOL" field="name" label="Name"/>
@@ -126,7 +132,7 @@
       <value type="STRING" field="type" label="Type" />
     </content_type>
 
-    <content_type id="GCThresholdUpdater" hr_name="GC Treshold Updater"
+    <content_type id="GCThresholdUpdater" hr_name="GC Threshold Updater"
                   type="U8" jvm_type="GCTHRESHOLDUPDATER">
       <value type="STRING" field="updater" label="Updater" />
     </content_type>
@@ -146,7 +152,7 @@
       <value type="STRING" field="type" label="Type" />
     </content_type>
 
-    <content_type id="NarrowOopMode" hr_name="Narrow oop Mode"
+    <content_type id="NarrowOopMode" hr_name="Narrow Oop Mode"
                   type="U8" jvm_type="NARROWOOPMODE">
       <value type="STRING" field="mode" label="Mode" />
     </content_type>
@@ -181,7 +187,7 @@
       <value type="SYMBOL" field="name" label="Name"/>
       <value type="SYMBOL" field="version" label="Version"/>
       <value type="SYMBOL" field="location" label="Location"/>
-      <value type="CLASS" field="classLoader" label="Class Loader"/>
+      <value type="CLASSLOADER" field="classLoader" label="Class Loader"/>
     </content_type>
 
     <content_type id="Package" hr_name="Package"
@@ -303,6 +309,9 @@
     <primary_type symbol="CLASS" datatype="U8" contenttype="CLASS"
                   type="const Klass*" sizeop="sizeof(u8)"/>
 
+    <primary_type symbol="CLASSLOADER" datatype="U8" contenttype="CLASSLOADER"
+              type="const ClassLoaderData*" sizeop="sizeof(u8)"/>
+
     <primary_type symbol="MODULE" datatype="U8" contenttype="MODULE"
                   type="const ModuleEntry*" sizeop="sizeof(u8)"/>