6603316: Improve instrumentation for classes loaded at startup
Reviewed-by: xlu, mchung
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Mon Mar 23 10:42:20 2009 -0400
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Mar 25 13:09:28 2009 -0400
@@ -3230,7 +3230,7 @@
// print out the superclass.
const char * from = Klass::cast(this_klass())->external_name();
if (this_klass->java_super() != NULL) {
- tty->print("RESOLVE %s %s\n", from, instanceKlass::cast(this_klass->java_super())->external_name());
+ tty->print("RESOLVE %s %s (super)\n", from, instanceKlass::cast(this_klass->java_super())->external_name());
}
// print out each of the interface classes referred to by this class.
objArrayHandle local_interfaces(THREAD, this_klass->local_interfaces());
@@ -3240,7 +3240,7 @@
klassOop k = klassOop(local_interfaces->obj_at(i));
instanceKlass* to_class = instanceKlass::cast(k);
const char * to = to_class->external_name();
- tty->print("RESOLVE %s %s\n", from, to);
+ tty->print("RESOLVE %s %s (interface)\n", from, to);
}
}
}
--- a/hotspot/src/share/vm/prims/jni.cpp Mon Mar 23 10:42:20 2009 -0400
+++ b/hotspot/src/share/vm/prims/jni.cpp Wed Mar 25 13:09:28 2009 -0400
@@ -301,6 +301,10 @@
klassOop k = SystemDictionary::resolve_from_stream(class_name, class_loader,
Handle(), &st, CHECK_NULL);
+ if (TraceClassResolution && k != NULL) {
+ trace_class_resolution(k);
+ }
+
cls = (jclass)JNIHandles::make_local(
env, Klass::cast(k)->java_mirror());
return cls;
@@ -365,6 +369,10 @@
result = find_class_from_class_loader(env, sym, true, loader,
protection_domain, true, thread);
+ if (TraceClassResolution && result != NULL) {
+ trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result)));
+ }
+
// If we were the first invocation of jni_FindClass, we enable compilation again
// rather than just allowing invocation counter to overflow and decay.
// Controlled by flag DelayCompilationDuringStartup.
@@ -2646,7 +2654,12 @@
Handle protection_domain; // null protection domain
symbolHandle sym = oopFactory::new_symbol_handle(name, CHECK_NULL);
- return find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL);
+ jclass result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL);
+
+ if (TraceClassResolution && result != NULL) {
+ trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result)));
+ }
+ return result;
}
// These lookups are done with the NULL (bootstrap) ClassLoader to
--- a/hotspot/src/share/vm/prims/jvm.cpp Mon Mar 23 10:42:20 2009 -0400
+++ b/hotspot/src/share/vm/prims/jvm.cpp Wed Mar 25 13:09:28 2009 -0400
@@ -64,6 +64,7 @@
ResourceMark rm;
int line_number = -1;
const char * source_file = NULL;
+ const char * trace = "explicit";
klassOop caller = NULL;
JavaThread* jthread = JavaThread::current();
if (jthread->has_last_Java_frame()) {
@@ -107,12 +108,21 @@
(last_caller->name() == vmSymbols::loadClassInternal_name() ||
last_caller->name() == vmSymbols::loadClass_name())) {
found_it = true;
+ } else if (!vfst.at_end()) {
+ if (vfst.method()->is_native()) {
+ // JNI call
+ found_it = true;
+ }
}
if (found_it && !vfst.at_end()) {
// found the caller
caller = vfst.method()->method_holder();
line_number = vfst.method()->line_number_from_bci(vfst.bci());
- symbolOop s = instanceKlass::cast(vfst.method()->method_holder())->source_file_name();
+ if (line_number == -1) {
+ // show method name if it's a native method
+ trace = vfst.method()->name_and_sig_as_C_string();
+ }
+ symbolOop s = instanceKlass::cast(caller)->source_file_name();
if (s != NULL) {
source_file = s->as_C_string();
}
@@ -124,15 +134,15 @@
const char * to = Klass::cast(to_class)->external_name();
// print in a single call to reduce interleaving between threads
if (source_file != NULL) {
- tty->print("RESOLVE %s %s %s:%d (explicit)\n", from, to, source_file, line_number);
+ tty->print("RESOLVE %s %s %s:%d (%s)\n", from, to, source_file, line_number, trace);
} else {
- tty->print("RESOLVE %s %s (explicit)\n", from, to);
+ tty->print("RESOLVE %s %s (%s)\n", from, to, trace);
}
}
}
}
-static void trace_class_resolution(klassOop to_class) {
+void trace_class_resolution(klassOop to_class) {
EXCEPTION_MARK;
trace_class_resolution_impl(to_class, THREAD);
if (HAS_PENDING_EXCEPTION) {
@@ -3213,8 +3223,12 @@
}
Handle h_loader(THREAD, loader);
Handle h_prot (THREAD, protection_domain);
- return find_class_from_class_loader(env, name, true, h_loader, h_prot,
- false, thread);
+ jclass result = find_class_from_class_loader(env, name, true, h_loader, h_prot,
+ false, thread);
+ if (TraceClassResolution && result != NULL) {
+ trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result)));
+ }
+ return result;
JVM_END
--- a/hotspot/src/share/vm/prims/jvm_misc.hpp Mon Mar 23 10:42:20 2009 -0400
+++ b/hotspot/src/share/vm/prims/jvm_misc.hpp Wed Mar 25 13:09:28 2009 -0400
@@ -27,6 +27,7 @@
jclass find_class_from_class_loader(JNIEnv* env, symbolHandle name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS);
+void trace_class_resolution(klassOop to_class);
/*
* Support for Serialization and RMI. Currently used by HotSpot only.