8079408: Reimplement TraceClassLoading, TraceClassUnloading, and TraceClassLoaderData with Unified Logging.
Summary: TraceClassLoading, TraceClassUnloading, and TraceClassLoaderData have been reimplemented using Unified logging.
Reviewed-by: iklam, coleenp, dholmes, jiangli, hseigel, rprotacio
Contributed-by: max.ockner@oracle.com, ioi.lam@oracle.com
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Feb 03 11:40:30 2016 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -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,12 @@
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);
+ }
+ // No 'else' here as logging levels are not mutually exclusive
+ if (log_is_enabled(Debug, classload)) {
+ ik->print_loading_log(LogLevel::Debug, _loader_data, _stream);
}
if (log_is_enabled(Info, classresolve)) {
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Wed Feb 03 11:40:30 2016 -0500
@@ -578,15 +578,14 @@
}
}
}
- if (TraceClassLoading || TraceClassPaths) {
+ if (TraceClassPaths) {
tty->print_cr("[Opened %s]", path);
}
+ log_info(classload)("opened: %s", path);
} else {
// Directory
new_entry = new ClassPathDirEntry(path);
- if (TraceClassLoading) {
- tty->print_cr("[Path %s]", path);
- }
+ log_info(classload)("path: %s", path);
}
return new_entry;
}
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Wed Feb 03 11:40:30 2016 -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,9 @@
_klasses = k;
}
- if (publicize && TraceClassLoaderData && Verbose && k->class_loader_data() != NULL) {
+ if (publicize && k->class_loader_data() != NULL) {
ResourceMark rm;
- tty->print_cr("[TraceClassLoaderData] Adding k: " PTR_FORMAT " %s to CLD: "
+ log_trace(classloaderdata)("Adding k: " PTR_FORMAT " %s to CLD: "
PTR_FORMAT " loader: " PTR_FORMAT " %s",
p2i(k),
k->external_name(),
@@ -326,15 +328,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 +411,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 {
@@ -601,21 +604,47 @@
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)) {
+ PauseNoSafepointVerifier pnsv(&no_safepoints); // Need safe points for JavaCalls::call_virtual
+ log_creation(loader, cld, CHECK_NULL);
}
return cld;
}
next = exchanged;
} while (true);
+}
+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);
@@ -709,10 +738,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();
}
}
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Wed Feb 03 11:40:30 2016 -0500
@@ -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
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Wed Feb 03 11:40:30 2016 -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();
}
@@ -3958,7 +3958,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;
}
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Feb 03 11:40:30 2016 -0500
@@ -1302,14 +1302,13 @@
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);
+ }
+ // No 'else' here as logging levels are not mutually exclusive
+
+ if (log_is_enabled(Debug, classload)) {
+ ik()->print_loading_log(LogLevel::Debug, loader_data, NULL);
}
if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
--- a/hotspot/src/share/vm/code/nmethod.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/code/nmethod.cpp Wed Feb 03 11:40:30 2016 -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
@@ -1310,13 +1311,14 @@
flush_dependencies(is_alive);
// Break cycle between nmethod & method
- if (TraceClassUnloading && WizardMode) {
- tty->print_cr("[Class unloading: Making nmethod " INTPTR_FORMAT
- " unloadable], Method*(" INTPTR_FORMAT
+ if (log_is_enabled(Trace, classunload)) {
+ outputStream* log = LogHandle(classunload)::trace_stream();
+ log->print_cr("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()) {
--- a/hotspot/src/share/vm/logging/logTag.hpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/logging/logTag.hpp Wed Feb 03 11:40:30 2016 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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) /* Trace all classes loaded */ \
+ LOG_TAG(classloaderdata) /* class loader loader_data lifetime */ \
+ LOG_TAG(classunload) /* Trace unloading of classes */ \
LOG_TAG(comp) \
LOG_TAG(compaction) \
LOG_TAG(cpu) \
--- a/hotspot/src/share/vm/memory/filemap.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/memory/filemap.cpp Wed Feb 03 11:40:30 2016 -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,7 +208,7 @@
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);
}
} else {
@@ -275,7 +275,7 @@
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 (os::stat(name, &st) != 0) {
@@ -301,7 +301,7 @@
}
}
if (ok) {
- if (TraceClassPaths || (TraceClassLoading && Verbose)) {
+ if (TraceClassPaths) {
tty->print_cr("[ok]");
}
} else if (!PrintSharedArchiveAndExit) {
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Feb 03 11:40:30 2016 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "classfile/classFileParser.hpp"
+#include "classfile/classFileStream.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/verifier.hpp"
@@ -35,6 +36,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 +2906,79 @@
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) {
+ log->print(" source: instance of %s", caller->external_name());
+ } else {
+ // source is unknown
+ }
+ } else {
+ Handle class_loader(loader_data->class_loader());
+ log->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 {
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Feb 03 11:40:30 2016 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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"
@@ -1244,6 +1245,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;
};
// for adding methods
--- a/hotspot/src/share/vm/oops/klass.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/oops/klass.cpp Wed Feb 03 11:40:30 2016 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -28,6 +28,7 @@
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
+#include "logging/log.hpp"
#include "memory/heapInspection.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/oopFactory.hpp"
@@ -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();
}
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp Wed Feb 03 11:40:30 2016 -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,9 +474,7 @@
ObjectLocker ol(loader_lock, thread);
// add the jar file to the bootclasspath
- if (TraceClassLoading) {
- tty->print_cr("[Opened %s]", zip_entry->name());
- }
+ log_info(classload)("opened: %s", zip_entry->name());
ClassLoaderExt::append_boot_classpath(zip_entry);
return JVMTI_ERROR_NONE;
} else {
@@ -625,8 +624,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) {
--- a/hotspot/src/share/vm/prims/whitebox.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Wed Feb 03 11:40:30 2016 -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
@@ -1407,7 +1407,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
--- a/hotspot/src/share/vm/runtime/arguments.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Feb 03 11:40:30 2016 -0500
@@ -402,10 +402,12 @@
};
static AliasedLoggingFlag const aliased_logging_flags[] = {
- { "TraceClassResolution", LogLevel::Info, true, LogTag::_classresolve },
- { "TraceExceptions", LogLevel::Info, true, LogTag::_exceptions },
- { "TraceMonitorInflation", LogLevel::Debug, true, LogTag::_monitorinflation },
- { NULL, LogLevel::Off, false, LogTag::__NO_TAG }
+ { "TraceClassLoading", LogLevel::Info, true, LogTag::_classload },
+ { "TraceClassUnloading", LogLevel::Info, true, LogTag::_classunload },
+ { "TraceClassResolution", LogLevel::Info, true, LogTag::_classresolve },
+ { "TraceExceptions", LogLevel::Info, true, LogTag::_exceptions },
+ { "TraceMonitorInflation", LogLevel::Debug, true, LogTag::_monitorinflation },
+ { NULL, LogLevel::Off, false, LogTag::__NO_TAG }
};
// Return true if "v" is less than "other", where "other" may be "undefined".
@@ -2653,12 +2655,8 @@
// -verbose:[class/gc/jni]
if (match_option(option, "-verbose", &tail)) {
if (!strcmp(tail, ":class") || !strcmp(tail, "")) {
- if (FLAG_SET_CMDLINE(bool, TraceClassLoading, true) != Flag::SUCCESS) {
- return JNI_EINVAL;
- }
- if (FLAG_SET_CMDLINE(bool, TraceClassUnloading, true) != Flag::SUCCESS) {
- return JNI_EINVAL;
- }
+ LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(classload));
+ LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(classunload));
} else if (!strcmp(tail, ":gc")) {
LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(gc));
} else if (!strcmp(tail, ":jni")) {
--- a/hotspot/src/share/vm/runtime/globals.hpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Feb 03 11:40:30 2016 -0500
@@ -2416,21 +2416,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") \
--- a/hotspot/src/share/vm/services/classLoadingService.cpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/services/classLoadingService.cpp Wed Feb 03 11:40:30 2016 -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,12 +181,13 @@
bool ClassLoadingService::set_verbose(bool verbose) {
MutexLocker m(Management_lock);
-
// 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) {
+ LogConfiguration::parse_log_arguments("stdout", "classload=info", NULL, NULL, NULL);
+ } else {
+ LogConfiguration::parse_log_arguments("stdout", "classload=off", NULL, NULL, NULL);
+ }
reset_trace_class_unloading();
-
return verbose;
}
@@ -192,8 +195,11 @@
void ClassLoadingService::reset_trace_class_unloading() {
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) {
+ LogConfiguration::parse_log_arguments("stdout", "classunload=info", NULL, NULL, NULL);
+ } else {
+ LogConfiguration::parse_log_arguments("stdout", "classunload=off", NULL, NULL, NULL);
+ }
}
GrowableArray<KlassHandle>* LoadedClassesEnumerator::_loaded_classes = NULL;
--- a/hotspot/src/share/vm/services/classLoadingService.hpp Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/src/share/vm/services/classLoadingService.hpp Wed Feb 03 11:40:30 2016 -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;
--- a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java Wed Feb 03 11:40:30 2016 -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
@@ -24,7 +24,7 @@
/**
* @test
* @bug 8057967
- * @run main/bootclasspath -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceClassUnloading
+ * @run main/bootclasspath -Xbatch -XX:+IgnoreUnrecognizedVMOptions -Xlog:classunload
* -XX:+PrintCompilation -XX:+TraceDependencies -XX:+TraceReferenceGC
* -verbose:gc java.lang.invoke.CallSiteDepContextTest
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/logging/ClassLoadUnloadTest.java Wed Feb 03 11:40:30 2016 -0500
@@ -0,0 +1,128 @@
+/*
+ * 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 ClassLoadUnloadTest
+ * @bug 8142506
+ * @library /testlibrary /runtime/testlibrary
+ * @library classes
+ * @build ClassUnloadCommon test.Empty jdk.test.lib.* jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools
+ * @run driver ClassLoadUnloadTest
+ */
+
+import jdk.test.lib.*;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ClassLoadUnloadTest {
+ private static OutputAnalyzer out;
+ private static ProcessBuilder pb;
+ private static class ClassUnloadTestMain {
+ public static void main(String... args) throws Exception {
+ String className = "test.Empty";
+ ClassLoader cl = ClassUnloadCommon.newClassLoader();
+ Class<?> c = cl.loadClass(className);
+ cl = null; c = null;
+ ClassUnloadCommon.triggerUnloading();
+ }
+ }
+
+ static void checkFor(String... outputStrings) throws Exception {
+ out = new OutputAnalyzer(pb.start());
+ for (String s: outputStrings) {
+ out.shouldContain(s);
+ }
+ out.shouldHaveExitValue(0);
+ }
+
+ static void checkAbsent(String... outputStrings) throws Exception {
+ out = new OutputAnalyzer(pb.start());
+ for (String s: outputStrings) {
+ out.shouldNotContain(s);
+ }
+ out.shouldHaveExitValue(0);
+ }
+
+ // Use the same command-line heap size setting as ../ClassUnload/UnloadTest.java
+ static ProcessBuilder exec(String... args) throws Exception {
+ List<String> argsList = new ArrayList<>();
+ Collections.addAll(argsList, args);
+ Collections.addAll(argsList, "-Xmn8m");
+ Collections.addAll(argsList, "-Dtest.classes=" + System.getProperty("test.classes","."));
+ Collections.addAll(argsList, ClassUnloadTestMain.class.getName());
+ return ProcessTools.createJavaProcessBuilder(argsList.toArray(new String[argsList.size()]));
+ }
+
+ public static void main(String... args) throws Exception {
+
+ // -Xlog:classunload=info
+ pb = exec("-Xlog:classunload=info");
+ checkFor("[classunload]", "unloading class");
+
+ // -Xlog:classunload=off
+ pb = exec("-Xlog:classunload=off");
+ checkAbsent("[classunload]");
+
+ // -XX:+TraceClassUnloading
+ pb = exec("-XX:+TraceClassUnloading");
+ checkFor("[classunload]", "unloading class");
+
+ // -XX:-TraceClassUnloading
+ pb = exec("-XX:-TraceClassUnloading");
+ checkAbsent("[classunload]");
+
+ // -Xlog:classload=info
+ pb = exec("-Xlog:classload=info");
+ checkFor("[classload]", "java.lang.Object", "source:");
+
+ // -Xlog:classload=debug
+ pb = exec("-Xlog:classload=debug");
+ checkFor("[classload]", "java.lang.Object", "source:", "klass:", "super:", "loader:", "bytes:");
+
+ // -Xlog:classload=off
+ pb = exec("-Xlog:classload=off");
+ checkAbsent("[classload]");
+
+ // -XX:+TraceClassLoading
+ pb = exec("-XX:+TraceClassLoading");
+ checkFor("[classload]", "java.lang.Object", "source:");
+
+ // -XX:-TraceClassLoading
+ pb = exec("-XX:-TraceClassLoading");
+ checkAbsent("[classload]");
+
+ // -verbose:class
+ pb = exec("-verbose:class");
+ checkFor("[classload]", "java.lang.Object", "source:");
+ checkFor("[classunload]", "unloading class");
+
+ // -Xlog:classloaderdata=trace
+ pb = exec("-Xlog:classloaderdata=trace");
+ checkFor("[classloaderdata]", "create class loader data");
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/logging/classes/test/Empty.java Wed Feb 03 11:40:30 2016 -0500
@@ -0,0 +1,5 @@
+package test;
+
+public class Empty {
+public String toString() { return "nothing"; }
+}
--- a/hotspot/test/runtime/testlibrary/ClassUnloadCommon.java Tue Feb 02 14:54:05 2016 +0000
+++ b/hotspot/test/runtime/testlibrary/ClassUnloadCommon.java Wed Feb 03 11:40:30 2016 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -21,6 +21,12 @@
* questions.
*/
+
+/*
+ * To use ClassUnloadCommon from a sub-process, see hotspot/test/runtime/logging/ClassLoadUnloadTest.java
+ * for an example.
+ */
+
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;