# HG changeset patch # User iklam # Date 1448794020 28800 # Sun Nov 29 02:47:00 2015 -0800 # Node ID ee6a9fee593d0f4d640d9b6f283c2bc045d13099 # Parent 5e392c0702af4ad35e6b31dfb9e3650d13b53551 imported patch class_loading_log 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 @@ -34,6 +34,7 @@ #include "classfile/verifier.hpp" #include "classfile/vmSymbols.hpp" #include "gc/shared/gcLocker.hpp" +#include "logging/log.hpp" #include "memory/allocation.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" @@ -4327,6 +4328,13 @@ } } + if (log_is_enabled(Debug, classload)) { + this_klass()->print_loading_log(LogLevel::Debug, loader_data, cfs); + } + if (log_is_enabled(Trace, classload)) { + this_klass()->print_loading_log(LogLevel::Trace, loader_data, cfs); + } + if (TraceClassResolution) { ResourceMark rm; // print out the superclass. diff --git a/src/share/vm/classfile/classLoaderData.cpp b/src/share/vm/classfile/classLoaderData.cpp --- a/src/share/vm/classfile/classLoaderData.cpp +++ b/src/share/vm/classfile/classLoaderData.cpp @@ -54,12 +54,14 @@ #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" #include "gc/shared/gcLocker.hpp" +#include "logging/log.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.inline.hpp" +#include "runtime/javaCalls.hpp" #include "runtime/jniHandles.hpp" #include "runtime/mutex.hpp" #include "runtime/safepoint.hpp" @@ -282,9 +284,10 @@ // link the new item into the list _klasses = k; - if (TraceClassLoaderData && Verbose && k->class_loader_data() != NULL) { + if (log_is_enabled(Trace, classloaderdata) && k->class_loader_data() != NULL) { ResourceMark rm; - tty->print_cr("[TraceClassLoaderData] Adding k: " PTR_FORMAT " %s to CLD: " + outputStream* log = LogHandle(classloaderdata)::trace_stream(); + log->print_cr("Adding k: " PTR_FORMAT " %s to CLD: " PTR_FORMAT " loader: " PTR_FORMAT " %s", p2i(k), k->external_name(), @@ -322,15 +325,16 @@ // Tell serviceability tools these classes are unloading classes_do(InstanceKlass::notify_unload_class); - if (TraceClassLoaderData) { + if (log_is_enabled(Debug, classloaderdata)) { ResourceMark rm; - tty->print("[ClassLoaderData: unload loader data " INTPTR_FORMAT, p2i(this)); - tty->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)class_loader()), + outputStream* log = LogHandle(classloaderdata)::debug_stream(); + log->print(": unload loader data " INTPTR_FORMAT, p2i(this)); + log->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)class_loader()), loader_name()); if (is_anonymous()) { - tty->print(" for anonymous class " INTPTR_FORMAT " ", p2i(_klasses)); + log->print(" for anonymous class " INTPTR_FORMAT " ", p2i(_klasses)); } - tty->print_cr("]"); + log->cr(); } } @@ -404,13 +408,13 @@ assert (class_loader() == NULL, "Must be"); set_metaspace(new Metaspace(_metaspace_lock, Metaspace::BootMetaspaceType)); } else if (is_anonymous()) { - if (TraceClassLoaderData && Verbose && class_loader() != NULL) { - tty->print_cr("is_anonymous: %s", class_loader()->klass()->internal_name()); + if (class_loader() != NULL) { + log_trace(classloaderdata)("is_anonymous: %s", class_loader()->klass()->internal_name()); } set_metaspace(new Metaspace(_metaspace_lock, Metaspace::AnonymousMetaspaceType)); } else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) { - if (TraceClassLoaderData && Verbose && class_loader() != NULL) { - tty->print_cr("is_reflection: %s", class_loader()->klass()->internal_name()); + if (class_loader() != NULL) { + log_trace(classloaderdata)("is_reflection: %s", class_loader()->klass()->internal_name()); } set_metaspace(new Metaspace(_metaspace_lock, Metaspace::ReflectionMetaspaceType)); } else { @@ -597,13 +601,9 @@ cld->set_next(next); ClassLoaderData* exchanged = (ClassLoaderData*)Atomic::cmpxchg_ptr(cld, list_head, next); if (exchanged == next) { - if (TraceClassLoaderData) { - ResourceMark rm; - tty->print("[ClassLoaderData: "); - tty->print("create class loader data " INTPTR_FORMAT, p2i(cld)); - tty->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)cld->class_loader()), - cld->loader_name()); - tty->print_cr("]"); + if (log_is_enabled(Debug, classloaderdata)) { + Pause_No_Safepoint_Verifier pnsv(&no_safepoints); // Need safe points for JavaCalls::call_virtual + log_creation(loader, cld, CHECK_NULL); } return cld; } @@ -612,6 +612,36 @@ } +void ClassLoaderDataGraph::log_creation(Handle loader, ClassLoaderData* cld, TRAPS) { + Handle string; + if (loader.not_null()) { + // Include the result of loader.toString() in the output. This allows + // the user of the log to identify the class loader instance. + JavaValue result(T_OBJECT); + KlassHandle spec_klass(THREAD, SystemDictionary::ClassLoader_klass()); + JavaCalls::call_virtual(&result, + loader, + spec_klass, + vmSymbols::toString_name(), + vmSymbols::void_string_signature(), + CHECK); + assert(result.get_type() == T_OBJECT, "just checking"); + string = (oop)result.get_jobject(); + } + + ResourceMark rm; + outputStream* log = LogHandle(classloaderdata)::debug_stream(); + log->print("create class loader data " INTPTR_FORMAT, p2i(cld)); + log->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)cld->class_loader()), + cld->loader_name()); + + if (string.not_null()) { + log->print(": "); + java_lang_String::print(string(), log); + } + log->cr(); +} + void ClassLoaderDataGraph::oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) { for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { cld->oops_do(f, klass_closure, must_claim); @@ -705,10 +735,11 @@ if (!curr->claimed()) { array->push(curr); - if (TraceClassLoaderData) { - tty->print("[ClassLoaderData] found new CLD: "); - curr->print_value_on(tty); - tty->cr(); + if (log_is_enabled(Debug, classloaderdata)) { + outputStream* log = LogHandle(classloaderdata)::debug_stream(); + log->print("found new CLD: "); + curr->print_value_on(log); + log->cr(); } } diff --git a/src/share/vm/classfile/classLoaderData.hpp b/src/share/vm/classfile/classLoaderData.hpp --- a/src/share/vm/classfile/classLoaderData.hpp +++ b/src/share/vm/classfile/classLoaderData.hpp @@ -116,6 +116,7 @@ static void dump_on(outputStream * const out) PRODUCT_RETURN; static void dump() { dump_on(tty); } static void verify(); + static void log_creation(Handle loader, ClassLoaderData* cld, TRAPS); static bool unload_list_contains(const void* x); #ifndef PRODUCT diff --git a/src/share/vm/classfile/systemDictionary.cpp b/src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp +++ b/src/share/vm/classfile/systemDictionary.cpp @@ -37,6 +37,7 @@ #include "gc/shared/gcLocker.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/interpreter.hpp" +#include "logging/log.hpp" #include "memory/filemap.hpp" #include "memory/oopFactory.hpp" #include "oops/instanceKlass.hpp" @@ -1286,6 +1287,13 @@ tty->print_cr("]"); } + if (log_is_enabled(Debug, classload)) { + ik()->print_loading_log(LogLevel::Debug, loader_data, NULL); + } + if (log_is_enabled(Trace, classload)) { + ik()->print_loading_log(LogLevel::Trace, loader_data, NULL); + } + if (DumpLoadedClassList != NULL && classlist_file->is_open()) { // Only dump the classes that can be stored into CDS archive if (SystemDictionaryShared::is_sharing_possible(loader_data)) { diff --git a/src/share/vm/logging/logTag.hpp b/src/share/vm/logging/logTag.hpp --- a/src/share/vm/logging/logTag.hpp +++ b/src/share/vm/logging/logTag.hpp @@ -31,6 +31,8 @@ // (The tags 'all', 'disable' and 'help' are special tags that can // not be used in log calls, and should not be listed below.) #define LOG_TAG_LIST \ + LOG_TAG(classload) \ + LOG_TAG(classloaderdata) \ LOG_TAG(defaultmethods) \ LOG_TAG(logging) \ LOG_TAG(safepoint) \ diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp +++ b/src/share/vm/oops/instanceKlass.cpp @@ -33,6 +33,7 @@ #include "interpreter/oopMapCache.hpp" #include "interpreter/rewriter.hpp" #include "jvmtifiles/jvmti.h" +#include "logging/log.hpp" #include "memory/heapInspection.hpp" #include "memory/iterator.inline.hpp" #include "memory/metadataFactory.hpp" @@ -3031,6 +3032,72 @@ return external_name(); } +void InstanceKlass::print_loading_log(LogLevel::type type, ClassLoaderData* loader_data, ClassFileStream* cfs) const { + ResourceMark rm; + outputStream* log; + + assert(type == LogLevel::Debug || type == LogLevel::Trace, "sanity"); + + if (type == LogLevel::Debug) { + log = LogHandle(classload)::debug_stream(); + } else { + assert(type == LogLevel::Trace, "print_loading_log supports only Debug and Trace levels"); + log = LogHandle(classload)::trace_stream(); + } + + // Name and class hierarchy info + log->print("%s", external_name()); + + // Source + if (cfs != NULL) { + if (cfs->source() != NULL) { + log->print(" source: %s", cfs->source()); + } else if (loader_data == ClassLoaderData::the_null_class_loader_data()) { + Thread* THREAD = Thread::current(); + 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(" source: instance of %s", caller->external_name()); + } else { + // source is unknown + } + } else { + Handle class_loader(loader_data->class_loader()); + tty->print(" source: %s", class_loader->klass()->external_name()); + } + } else { + log->print(" source: shared objects file"); + } + + if (type == LogLevel::Trace) { + // Class hierarchy info + log->print(" klass: " INTPTR_FORMAT " super: " INTPTR_FORMAT, + p2i(this), p2i(superklass())); + + if (local_interfaces() != NULL && local_interfaces()->length() > 0) { + log->print(" interfaces:"); + int length = local_interfaces()->length(); + for (int i = 0; i < length; i++) { + log->print(" " INTPTR_FORMAT, p2i(InstanceKlass::cast(local_interfaces()->at(i)))); + } + } + + // Class loader + log->print(" loader: ["); + loader_data->print_value_on(log); + log->print("]"); + + // Classfile checksum + if (cfs) { + log->print(" bytes: %d checksum: %08x", cfs->length(), ClassLoader::crc32(0, (const char*)cfs->buffer(), cfs->length())); + } + } + log->cr(); +} + #if INCLUDE_SERVICES // Size Statistics void InstanceKlass::collect_statistics(KlassSizeStats *sz) const { diff --git a/src/share/vm/oops/instanceKlass.hpp b/src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp +++ b/src/share/vm/oops/instanceKlass.hpp @@ -27,6 +27,7 @@ #include "classfile/classLoaderData.hpp" #include "gc/shared/specialized_oop_closures.hpp" +#include "logging/logLevel.hpp" #include "memory/referenceType.hpp" #include "oops/annotations.hpp" #include "oops/constMethod.hpp" @@ -1262,6 +1263,9 @@ void verify_on(outputStream* st); void oop_verify_on(oop obj, outputStream* st); + + // Logging + void print_loading_log(LogLevel::type type, ClassLoaderData* loader_data, ClassFileStream* cfs) const; }; inline Method* InstanceKlass::method_at_vtable(int index) { diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp +++ b/src/share/vm/runtime/globals.hpp @@ -2468,9 +2468,6 @@ product_rw(bool, TraceLoaderConstraints, false, \ "Trace loader constraints") \ \ - develop(bool, TraceClassLoaderData, false, \ - "Trace class loader loader_data lifetime") \ - \ product(size_t, InitialBootClassLoaderMetaspaceSize, \ NOT_LP64(2200*K) LP64_ONLY(4*M), \ "Initial size of the boot class loader data metaspace") \