diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp index b1f61dcf69a58392462d413a6a77eb1e8f37eb83..119b95adf46485593db6263820a4f91c6435db56 100644 --- a/src/share/vm/classfile/classFileParser.cpp +++ b/src/share/vm/classfile/classFileParser.cpp @@ -3230,7 +3230,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, // 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 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, 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); } } } diff --git a/src/share/vm/prims/jni.cpp b/src/share/vm/prims/jni.cpp index bd4f1ec3223a020a8aa883d31d7f2b4036ec6772..bde5dba7771525e60b68a876421cc553d38d12eb 100644 --- a/src/share/vm/prims/jni.cpp +++ b/src/share/vm/prims/jni.cpp @@ -301,6 +301,10 @@ JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderR 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 @@ JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name)) 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 @@ static jclass lookupOne(JNIEnv* env, const char* name, TRAPS) { 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 diff --git a/src/share/vm/prims/jvm.cpp b/src/share/vm/prims/jvm.cpp index cf866df9f61481a167e0d428039095b933b1f26a..5d341330506362c95ec45313e70a9b7b8f868050 100644 --- a/src/share/vm/prims/jvm.cpp +++ b/src/share/vm/prims/jvm.cpp @@ -64,6 +64,7 @@ static void trace_class_resolution_impl(klassOop to_class, TRAPS) { 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 @@ static void trace_class_resolution_impl(klassOop to_class, TRAPS) { (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 @@ static void trace_class_resolution_impl(klassOop to_class, TRAPS) { 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 @@ JVM_ENTRY(jclass, JVM_LoadClass0(JNIEnv *env, jobject receiver, } 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 diff --git a/src/share/vm/prims/jvm_misc.hpp b/src/share/vm/prims/jvm_misc.hpp index 7af47518c0feb64ae4a07b8d7cbd3ceaff19fe7b..50644842bbd136c40fd175446a7a4fd4e077e91a 100644 --- a/src/share/vm/prims/jvm_misc.hpp +++ b/src/share/vm/prims/jvm_misc.hpp @@ -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.