--- old/src/share/vm/oops/klass.cpp 2016-01-08 01:43:04.911245767 -0500 +++ new/src/share/vm/oops/klass.cpp 2016-01-08 01:43:04.681647331 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -40,6 +40,7 @@ #include "trace/traceMacros.hpp" #include "utilities/macros.hpp" #include "utilities/stack.inline.hpp" +#include "logging/log.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/g1SATBCardTableModRefBS.hpp" #endif // INCLUDE_ALL_GCS @@ -386,9 +387,9 @@ Klass* sub = current->subklass(); while (sub != NULL && !sub->is_loader_alive(is_alive)) { #ifndef PRODUCT - if (TraceClassUnloading && WizardMode) { + if (log_is_enabled(Trace, classunload)) { ResourceMark rm; - tty->print_cr("[Unlinking class (subclass) %s]", sub->external_name()); + log_trace(classunload)("[Unlinking class (subclass) %s]", sub->external_name()); } #endif sub = sub->next_sibling(); @@ -401,9 +402,9 @@ // Find and set the first alive sibling Klass* sibling = current->next_sibling(); while (sibling != NULL && !sibling->is_loader_alive(is_alive)) { - if (TraceClassUnloading && WizardMode) { + if (log_is_enabled(Trace, classunload)) { ResourceMark rm; - tty->print_cr("[Unlinking class (sibling) %s]", sibling->external_name()); + log_trace(classunload)("[Unlinking class (sibling) %s]", sibling->external_name()); } sibling = sibling->next_sibling(); } --- old/src/share/vm/memory/filemap.cpp 2016-01-08 01:43:04.922467332 -0500 +++ new/src/share/vm/memory/filemap.cpp 2016-01-08 01:43:04.666214663 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -208,9 +208,12 @@ count ++; bytes += (int)entry_size; bytes += name_bytes; - if (TraceClassPaths || (TraceClassLoading && Verbose)) { + if (TraceClassPaths) { tty->print_cr("[Add main shared path (%s) %s]", (cpe->is_jar_file() ? "jar" : "dir"), name); } + if (log_is_enabled(Debug, classload)) { + log_debug(classload)("[Add main shared path (%s) %s]", (cpe->is_jar_file() ? "jar" : "dir"), name); + } } else { SharedClassPathEntry* ent = shared_classpath(cur_entry); if (cpe->is_jar_file()) { @@ -275,9 +278,12 @@ struct stat st; const char* name = ent->_name; bool ok = true; - if (TraceClassPaths || (TraceClassLoading && Verbose)) { + if (TraceClassPaths) { tty->print_cr("[Checking shared classpath entry: %s]", name); } + if (log_is_enabled(Debug, classload)) { + log_debug(classload)("[Checking shared classpath entry: %s]", name); + } if (os::stat(name, &st) != 0) { fail_continue("Required classpath entry does not exist: %s", name); ok = false; @@ -301,9 +307,12 @@ } } if (ok) { - if (TraceClassPaths || (TraceClassLoading && Verbose)) { + if (TraceClassPaths) { tty->print_cr("[ok]"); } + if (log_is_enabled(Debug, classload)) { + log_debug(classload)("[ok]"); + } } else if (!PrintSharedArchiveAndExit) { _validating_classpath_entry_table = false; return false; --- old/src/share/vm/logging/logTag.hpp 2016-01-08 01:43:04.888828217 -0500 +++ new/src/share/vm/logging/logTag.hpp 2016-01-08 01:43:04.662484126 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -39,6 +39,9 @@ LOG_TAG(classhisto) \ LOG_TAG(classresolve) \ LOG_TAG(classinit) \ + LOG_TAG(classload) \ + LOG_TAG(classloaderdata) \ + LOG_TAG(classunload) \ LOG_TAG(comp) \ LOG_TAG(compaction) \ LOG_TAG(cpu) \ --- old/src/share/vm/oops/instanceKlass.hpp 2016-01-08 01:43:04.922471260 -0500 +++ new/src/share/vm/oops/instanceKlass.hpp 2016-01-08 01:43:04.662155336 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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,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" @@ -1256,6 +1257,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, const ClassFileStream* cfs) const; }; inline Method* InstanceKlass::method_at_vtable(int index) { --- old/src/share/vm/classfile/systemDictionary.cpp 2016-01-08 01:43:04.900123748 -0500 +++ new/src/share/vm/classfile/systemDictionary.cpp 2016-01-08 01:43:04.628066383 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -42,6 +42,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" @@ -1302,14 +1303,11 @@ ik->restore_unshareable_info(loader_data, protection_domain, CHECK_(nh)); } - if (TraceClassLoading) { - ResourceMark rm; - tty->print("[Loaded %s", ik->external_name()); - tty->print(" from shared objects file"); - if (class_loader.not_null()) { - tty->print(" by %s", loader_data->loader_name()); - } - tty->print_cr("]"); + if (log_is_enabled(Info, classload)) { + ik()->print_loading_log(LogLevel::Info, loader_data, NULL); + } + if (log_is_enabled(Debug, classload)) { + ik()->print_loading_log(LogLevel::Debug, loader_data, NULL); } if (DumpLoadedClassList != NULL && classlist_file->is_open()) { --- old/src/share/vm/classfile/classLoaderData.cpp 2016-01-08 01:43:04.888419153 -0500 +++ new/src/share/vm/classfile/classLoaderData.cpp 2016-01-08 01:43:04.720738740 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, 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 @@ -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" @@ -286,9 +288,10 @@ _klasses = k; } - if (publicize && TraceClassLoaderData && Verbose && k->class_loader_data() != NULL) { + if (publicize && 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(), @@ -326,15 +329,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(); } } @@ -408,13 +412,15 @@ 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 (log_is_enabled(Trace, classloaderdata) && class_loader() != NULL) { + outputStream* log = LogHandle(classloaderdata)::trace_stream(); + log->print_cr("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 (log_is_enabled(Trace, classloaderdata) && class_loader() != NULL) { + outputStream* log = LogHandle(classloaderdata)::trace_stream(); + log->print_cr("is_reflection: %s", class_loader()->klass()->internal_name()); } set_metaspace(new Metaspace(_metaspace_lock, Metaspace::ReflectionMetaspaceType)); } else { @@ -573,13 +579,16 @@ // We need to allocate all the oops for the ClassLoaderData before allocating the // actual ClassLoaderData object. ClassLoaderData::Dependencies dependencies(CHECK_NULL); + ClassLoaderData* cld; + +//BEGIN no_safepoints +{ No_Safepoint_Verifier no_safepoints; // we mustn't GC until we've installed the // ClassLoaderData in the graph since the CLD // contains unhandled oops - ClassLoaderData* cld = new ClassLoaderData(loader, is_anonymous, dependencies); - + cld = new ClassLoaderData(loader, is_anonymous, dependencies); if (!is_anonymous) { ClassLoaderData** cld_addr = java_lang_ClassLoader::loader_data_addr(loader()); @@ -601,19 +610,44 @@ 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("]"); - } - return cld; + break; } next = exchanged; } while (true); + } +//END no_safepoints + + // It's OK to do safe points now (and we need to do that in JavaCalls::call_virtual) + if (log_is_enabled(Debug, classloaderdata)) { + 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_NULL); + 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(); + } + return cld; } void ClassLoaderDataGraph::oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) { @@ -709,10 +743,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("[ClassLoaderData] found new CLD: "); + curr->print_value_on(log); + log->cr(); } } --- old/src/share/vm/classfile/classLoader.cpp 2016-01-08 01:43:04.936829589 -0500 +++ new/src/share/vm/classfile/classLoader.cpp 2016-01-08 01:43:04.662138725 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -37,6 +37,7 @@ #include "gc/shared/generation.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/oopMapCache.hpp" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "memory/oopFactory.hpp" @@ -577,14 +578,16 @@ } } } - if (TraceClassLoading || TraceClassPaths) { - tty->print_cr("[Opened %s]", path); + if (log_is_enabled(Info, classload)) { + outputStream* log = LogHandle(classload)::info_stream(); + log->print_cr("[Opened %s]", path); } } else { // Directory new_entry = new ClassPathDirEntry(path); - if (TraceClassLoading) { - tty->print_cr("[Path %s]", path); + if (log_is_enabled(Info, classload)) { + outputStream* log = LogHandle(classload)::info_stream(); + log->print_cr("[Path %s]", path); } } return new_entry; --- old/src/share/vm/classfile/javaClasses.cpp 2016-01-08 01:43:04.922693447 -0500 +++ new/src/share/vm/classfile/javaClasses.cpp 2016-01-08 01:43:04.681840030 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -129,7 +129,7 @@ tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int()); } #endif //PRODUCT - vm_exit_during_initialization("Invalid layout of preloaded class: use -XX:+TraceClassLoading to see the origin of the problem class"); + vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:classload=info to see the origin of the problem class"); } dest_offset = fd.offset(); } @@ -3965,7 +3965,7 @@ tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int()); } #endif //PRODUCT - vm_exit_during_initialization("Invalid layout of preloaded class: use -XX:+TraceClassLoading to see the origin of the problem class"); + vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:classload=info to see the origin of the problem class"); return -1; } --- old/src/share/vm/code/nmethod.cpp 2016-01-08 01:43:04.933676599 -0500 +++ new/src/share/vm/code/nmethod.cpp 2016-01-08 01:43:04.653356042 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -48,6 +48,7 @@ #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/xmlstream.hpp" +#include "logging/log.hpp" #ifdef TARGET_ARCH_x86 # include "nativeInst_x86.hpp" #endif @@ -1306,13 +1307,14 @@ flush_dependencies(is_alive); // Break cycle between nmethod & method - if (TraceClassUnloading && WizardMode) { - tty->print_cr("[Class unloading: Making nmethod " INTPTR_FORMAT + if (log_is_enabled(Trace, classunload)) { + outputStream* log = LogHandle(classunload)::trace_stream(); + log->print_cr("[Class unloading: Making nmethod " INTPTR_FORMAT " unloadable], Method*(" INTPTR_FORMAT "), cause(" INTPTR_FORMAT ")", p2i(this), p2i(_method), p2i(cause)); if (!Universe::heap()->is_gc_active()) - cause->klass()->print(); + cause->klass()->print_on(log); } // Unlink the osr method, so we do not look this up again if (is_osr_method()) { --- old/src/share/vm/oops/instanceKlass.cpp 2016-01-08 01:43:04.995850390 -0500 +++ new/src/share/vm/oops/instanceKlass.cpp 2016-01-08 01:43:04.641566645 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -35,6 +35,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" @@ -2904,6 +2905,72 @@ return external_name(); } +void InstanceKlass::print_loading_log(LogLevel::type type, ClassLoaderData* loader_data, const ClassFileStream* cfs) const { + ResourceMark rm; + outputStream* log; + + assert(type == LogLevel::Info || type == LogLevel::Debug, "sanity"); + + if (type == LogLevel::Info) { + log = LogHandle(classload)::info_stream(); + } else { + assert(type == LogLevel::Debug, "print_loading_log supports only Debug and Info levels"); + log = LogHandle(classload)::debug_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::Debug) { + // 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 { --- old/src/share/vm/prims/jvmtiEnv.cpp 2016-01-08 01:43:04.984666616 -0500 +++ new/src/share/vm/prims/jvmtiEnv.cpp 2016-01-08 01:43:04.692380982 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -29,6 +29,7 @@ #include "interpreter/bytecodeStream.hpp" #include "interpreter/interpreter.hpp" #include "jvmtifiles/jvmtiEnv.hpp" +#include "logging/log.hpp" #include "logging/logConfiguration.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" @@ -473,8 +474,9 @@ ObjectLocker ol(loader_lock, thread); // add the jar file to the bootclasspath - if (TraceClassLoading) { - tty->print_cr("[Opened %s]", zip_entry->name()); + if (log_is_enabled(Info, classload)) { + outputStream* log = LogHandle(classload)::info_stream(); + log->print_cr("[Opened %s]", zip_entry->name()); } ClassLoaderExt::append_boot_classpath(zip_entry); return JVMTI_ERROR_NONE; @@ -625,8 +627,13 @@ // ignore break; case JVMTI_VERBOSE_CLASS: - TraceClassLoading = value != 0; - TraceClassUnloading = value != 0; + if (value == 0) { + LogConfiguration::parse_log_arguments("stdout", "classunload=off", NULL, NULL, NULL); + LogConfiguration::parse_log_arguments("stdout", "classload=off", NULL, NULL, NULL); + } else { + LogConfiguration::parse_log_arguments("stdout", "classload=info", NULL, NULL, NULL); + LogConfiguration::parse_log_arguments("stdout", "classunload=info", NULL, NULL, NULL); + } break; case JVMTI_VERBOSE_GC: if (value == 0) { --- old/src/share/vm/classfile/classFileParser.cpp 2016-01-08 01:43:05.016054244 -0500 +++ new/src/share/vm/classfile/classFileParser.cpp 2016-01-08 01:43:04.712814485 -0500 @@ -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" @@ -5347,30 +5348,11 @@ ClassLoadingService::notify_class_loaded(ik, false /* not shared class */); if (!is_internal()) { - if (TraceClassLoading) { - ResourceMark rm; - // print in a single call to reduce interleaving of output - if (_stream->source() != NULL) { - tty->print("[Loaded %s from %s]\n", - ik->external_name(), - _stream->source()); - } else if (_loader_data->class_loader() == NULL) { - const Klass* const 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", - ik->external_name(), - caller->external_name()); - } else { - tty->print("[Loaded %s]\n", ik->external_name()); - } - } else { - tty->print("[Loaded %s from %s]\n", ik->external_name(), - _loader_data->class_loader()->klass()->external_name()); - } + if (log_is_enabled(Info, classload)) { + ik->print_loading_log(LogLevel::Info, _loader_data, _stream); + } + if (log_is_enabled(Debug, classload)) { + ik->print_loading_log(LogLevel::Debug, _loader_data, _stream); } if (log_is_enabled(Info, classresolve)) { --- /dev/null 2015-11-21 16:36:38.509275105 -0500 +++ new/test/runtime/logging/ClassLoadUnload.java 2016-01-08 01:43:06.798198474 -0500 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test ClassUnloadTest + * @bug 8142506 + * @library /testlibrary + * @run driver ClassUnloadTest + */ + +import jdk.test.lib.*; +import java.lang.ref.WeakReference; +import java.lang.reflect.Method; + +public class ClassUnloadTest { + private static OutputAnalyzer out; + private static ProcessBuilder pb; + private static class ClassUnloadTestMain { + + static String klass = "public class Empty {" + + " public void bigLoop(){}" + + " public String toString() { return \"nothing\"; } }"; + + public static volatile WeakReference clweak; + public static byte[] garbage; + + public static void main(String... args) throws Exception { + ByteCodeLoader cl = new ByteCodeLoader("Empty", InMemoryJavaCompiler.compile("Empty", klass)); + Class c = cl.loadClass("Empty"); + Object o = c.newInstance(); + Method m = c.getMethod("bigLoop"); + + for ( int i=0; i<10001; i++){ + m.invoke(o); + } + + clweak = new WeakReference<>(cl); + cl = null; c = null; o = null; m = null; + while(clweak.get() != null) { + garbage = new byte[8192]; + System.gc(); + } + } + } + + static void checkFor(String... outputStrings) throws Exception { + out = new OutputAnalyzer(pb.start()); + for (String s: outputStrings) { + out.shouldContain(s); + } + out.shouldHaveExitValue(0); + out.getOutput(); + } + + static void checkAbsent(String... outputStrings) throws Exception { + out = new OutputAnalyzer(pb.start()); + for (String s: outputStrings) { + out.shouldNotContain(s); + } + out.shouldHaveExitValue(0); + } + + public static void main(String... args) throws Exception { + + // (1) -Xlog:classunload=info + pb = ProcessTools.createJavaProcessBuilder( + "-Xlog:classunload=info", "-Xmx64m", ClassUnloadTestMain.class.getName() + ); + checkFor("[classunload]", "[Unloading class"); + + // (2) -Xlog:classunload=trace + pb = ProcessTools.createJavaProcessBuilder( + "-Xlog:classunload=trace", "-Xmx64m", ClassUnloadTestMain.class.getName() + ); + checkFor("[classunload]", "Class unloading: Making nmethod"); + + // (3) -Xlog:classunload=off + pb = ProcessTools.createJavaProcessBuilder( + "-Xlog:classunload=off", "-Xmx64m", ClassUnloadTestMain.class.getName() + ); + checkAbsent("[classunload]"); + + // (4) -XX:+TraceClassUnloading + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+TraceClassUnloading", "-Xmx64m", ClassUnloadTestMain.class.getName() + ); + checkFor("[classunload]", "[Unloading class"); + + // (5) -XX:-TraceClassUnloading + pb = ProcessTools.createJavaProcessBuilder( + "-XX:-TraceClassUnloading", "-Xmx64m", ClassUnloadTestMain.class.getName() + ); + checkAbsent("[classunload]"); + + // (6) -Xlog:classload=info + pb = ProcessTools.createJavaProcessBuilder( + "-Xlog:classload=info", "-Xmx64m", ClassUnloadTestMain.class.getName() + ); + checkFor("[classload]", "java.lang.Object", "source:"); + + // (7) -Xlog:classload=debug + pb = ProcessTools.createJavaProcessBuilder( + "-Xlog:classload=debug", "-Xmx64m", ClassUnloadTestMain.class.getName() + ); + checkFor("[classload]", "java.lang.Object", "source:", "klass:", "super:", "loader:", "bytes:"); + + // (8) -Xlog:classload=off + pb = ProcessTools.createJavaProcessBuilder( + "-Xlog:classload=off", "-Xmx64m", ClassUnloadTestMain.class.getName() + ); + checkAbsent("[classload]"); + + // (9) -XX:+TraceClassLoading + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+TraceClassLoading", "-Xmx64m", ClassUnloadTestMain.class.getName() + ); + checkFor("[classload]", "java.lang.Object", "source:"); + + // (10) -XX:-TraceClassLoading + pb = ProcessTools.createJavaProcessBuilder( + "-XX:-TraceClassLoading", "-Xmx64m", ClassUnloadTestMain.class.getName() + ); + checkAbsent("[classload]"); + + // (11) -verbose:class + pb = ProcessTools.createJavaProcessBuilder( + "-verbose:class", "-Xmx64m", ClassUnloadTestMain.class.getName() + ); + checkFor("[classload]", "java.lang.Object", "source:"); + checkFor("[classunload]", "[Unloading class"); + + // (12) -Xlog:classloaderdata=trace + pb = ProcessTools.createJavaProcessBuilder( + "-Xlog:classloaderdata=trace", "-Xmx64m", ClassUnloadTestMain.class.getName() + ); + checkFor("[classloaderdata]", "create class loader data"); + + } +} --- old/src/share/vm/prims/whitebox.cpp 2016-01-08 01:43:06.944947011 -0500 +++ new/src/share/vm/prims/whitebox.cpp 2016-01-08 01:43:06.797679513 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, 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 @@ -1402,7 +1402,7 @@ if (res == NULL) { tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string()); - vm_exit_during_initialization("Invalid layout of preloaded class: use -XX:+TraceClassLoading to see the origin of the problem class"); + vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:classload=info to see the origin of the problem class"); } //fetch the field at the offset we've found --- old/src/share/vm/runtime/arguments.cpp 2016-01-08 01:43:06.959061067 -0500 +++ new/src/share/vm/runtime/arguments.cpp 2016-01-08 01:43:06.791471529 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -402,6 +402,10 @@ static AliasedFlag const aliased_jvm_logging_flags[] = { { "-XX:+TraceClassResolution", "-Xlog:classresolve=info"}, { "-XX:-TraceClassResolution", "-Xlog:classresolve=off"}, + { "-XX:+TraceClassLoading", "-Xlog:classload=info"}, + { "-XX:-TraceClassLoading", "-Xlog:classload=off"}, + { "-XX:+TraceClassUnloading", "-Xlog:classunload=info"}, + { "-XX:-TraceClassUnloading", "-Xlog:classunload=off"}, { "-XX:+TraceExceptions", "-Xlog:exceptions=info" }, { "-XX:-TraceExceptions", "-Xlog:exceptions=off" }, { "-XX:+TraceMonitorInflation", "-Xlog:monitorinflation=debug" }, @@ -2655,16 +2659,19 @@ // -verbose:[class/gc/jni] if (match_option(option, "-verbose", &tail)) { + bool ret; if (!strcmp(tail, ":class") || !strcmp(tail, "")) { - if (FLAG_SET_CMDLINE(bool, TraceClassLoading, true) != Flag::SUCCESS) { + ret = LogConfiguration::parse_log_arguments("stdout", "classload=info", NULL, NULL, NULL); + if (!ret) { return JNI_EINVAL; } - if (FLAG_SET_CMDLINE(bool, TraceClassUnloading, true) != Flag::SUCCESS) { + ret = LogConfiguration::parse_log_arguments("stdout", "classunload=info", NULL, NULL, NULL); + if (!ret) { return JNI_EINVAL; } } else if (!strcmp(tail, ":gc")) { // LogConfiguration_lock is not set up yet, but this code is executed by a single thread - bool ret = LogConfiguration::parse_log_arguments("stdout", "gc", NULL, NULL, NULL); + ret = LogConfiguration::parse_log_arguments("stdout", "gc", NULL, NULL, NULL); if (!ret) { return JNI_EINVAL; } --- old/src/share/vm/services/classLoadingService.cpp 2016-01-08 01:43:06.996973004 -0500 +++ new/src/share/vm/services/classLoadingService.cpp 2016-01-08 01:43:06.801496906 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -33,6 +33,8 @@ #include "utilities/dtrace.hpp" #include "utilities/macros.hpp" #include "utilities/defaultStream.hpp" +#include "logging/log.hpp" +#include "logging/logConfiguration.hpp" #ifdef DTRACE_ENABLED @@ -135,9 +137,9 @@ } } - if (TraceClassUnloading) { + if (log_is_enabled(Info, classunload)) { ResourceMark rm; - tty->print_cr("[Unloading class %s " INTPTR_FORMAT "]", k->external_name(), p2i(k)); + log_info(classunload)("[Unloading class %s " INTPTR_FORMAT "]", k->external_name(), p2i(k)); } } @@ -179,21 +181,27 @@ bool ClassLoadingService::set_verbose(bool verbose) { MutexLocker m(Management_lock); - + bool ret; // verbose will be set to the previous value - Flag::Error error = CommandLineFlags::boolAtPut("TraceClassLoading", &verbose, Flag::MANAGEMENT); - assert(error==Flag::SUCCESS, "Setting TraceClassLoading flag failed with error %s", Flag::flag_error_str(error)); + if (verbose) { + ret = LogConfiguration::parse_log_arguments("stdout", "classload=info", NULL, NULL, NULL); + } else { + ret = LogConfiguration::parse_log_arguments("stdout", "classload=off", NULL, NULL, NULL); + } reset_trace_class_unloading(); - return verbose; } // Caller to this function must own Management_lock void ClassLoadingService::reset_trace_class_unloading() { + bool ret; assert(Management_lock->owned_by_self(), "Must own the Management_lock"); bool value = MemoryService::get_verbose() || ClassLoadingService::get_verbose(); - Flag::Error error = CommandLineFlags::boolAtPut("TraceClassUnloading", &value, Flag::MANAGEMENT); - assert(error==Flag::SUCCESS, "Setting TraceClassUnLoading flag failed with error %s", Flag::flag_error_str(error)); + if (value) { + ret = LogConfiguration::parse_log_arguments("stdout", "classunload=info", NULL, NULL, NULL); + } else { + ret = LogConfiguration::parse_log_arguments("stdout", "classunload=off", NULL, NULL, NULL); + } } GrowableArray* LoadedClassesEnumerator::_loaded_classes = NULL; --- old/src/share/vm/runtime/globals.hpp 2016-01-08 01:43:06.997299901 -0500 +++ new/src/share/vm/runtime/globals.hpp 2016-01-08 01:43:06.759477213 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -2397,21 +2397,12 @@ product(bool, TraceClassPaths, false, \ "Trace processing of class paths") \ \ - product_rw(bool, TraceClassLoading, false, \ - "Trace all classes loaded") \ - \ product(bool, TraceClassLoadingPreorder, false, \ "Trace all classes loaded in order referenced (not loaded)") \ \ - product_rw(bool, TraceClassUnloading, false, \ - "Trace unloading of classes") \ - \ 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") \ --- old/src/share/vm/services/classLoadingService.hpp 2016-01-08 01:43:06.996967986 -0500 +++ new/src/share/vm/services/classLoadingService.hpp 2016-01-08 01:43:06.800016233 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_SERVICES_CLASSLOADINGSERVICE_HPP #define SHARE_VM_SERVICES_CLASSLOADINGSERVICE_HPP +#include "logging/log.hpp" #include "runtime/handles.hpp" #include "runtime/perfData.hpp" #include "utilities/growableArray.hpp" @@ -54,7 +55,7 @@ public: static void init(); - static bool get_verbose() { return TraceClassLoading; } + static bool get_verbose() { return log_is_enabled(Info, classload); } static bool set_verbose(bool verbose); static void reset_trace_class_unloading() NOT_MANAGEMENT_RETURN;