--- old/src/hotspot/share/classfile/systemDictionary.cpp 2019-10-17 16:50:36.497955574 +0200 +++ new/src/hotspot/share/classfile/systemDictionary.cpp 2019-10-17 16:50:36.069953452 +0200 @@ -1937,6 +1937,85 @@ start_id = limit_id; } +bool SystemDictionary::register_native(Klass* k, Symbol* name, Symbol* signature, address entry, TRAPS) { + Method* method = k->lookup_method(name, signature); + if (method == NULL) { + ResourceMark rm; + stringStream st; + st.print("Method '"); + Method::print_external_name(&st, k, name, signature); + st.print("' name or signature does not match"); + THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false); + } + if (!method->is_native()) { + // trying to register to a non-native method, see if a JVM TI agent has added prefix(es) + method = find_prefixed_native(k, name, signature, THREAD); + if (method == NULL) { + ResourceMark rm; + stringStream st; + st.print("Method '"); + Method::print_external_name(&st, k, name, signature); + st.print("' is not declared as native"); + THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false); + } + } + + if (entry != NULL) { + method->set_native_function(entry, + Method::native_bind_event_is_interesting); + } else { + method->clear_native_function(); + } + if (PrintJNIResolving) { + ResourceMark rm(THREAD); + tty->print_cr("[Registering JNI native method %s.%s]", + method->method_holder()->external_name(), + method->name()->as_C_string()); + } + return true; +} + +// The RegisterNatives call being attempted tried to register with a method that +// is not native. Ask JVM TI what prefixes have been specified. Then check +// to see if the native method is now wrapped with the prefixes. See the +// SetNativeMethodPrefix(es) functions in the JVM TI Spec for details. +Method* SystemDictionary::find_prefixed_native(Klass* k, Symbol* name, Symbol* signature, TRAPS) { +#if INCLUDE_JVMTI + ResourceMark rm(THREAD); + Method* method; + int name_len = name->utf8_length(); + char* name_str = name->as_utf8(); + int prefix_count; + char** prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count); + for (int i = 0; i < prefix_count; i++) { + char* prefix = prefixes[i]; + int prefix_len = (int)strlen(prefix); + + // try adding this prefix to the method name and see if it matches another method name + int trial_len = name_len + prefix_len; + char* trial_name_str = NEW_RESOURCE_ARRAY(char, trial_len + 1); + strcpy(trial_name_str, prefix); + strcat(trial_name_str, name_str); + TempNewSymbol trial_name = SymbolTable::probe(trial_name_str, trial_len); + if (trial_name == NULL) { + continue; // no such symbol, so this prefix wasn't used, try the next prefix + } + method = k->lookup_method(trial_name, signature); + if (method == NULL) { + continue; // signature doesn't match, try the next prefix + } + if (method->is_native()) { + method->set_is_prefixed_native(); + return method; // wahoo, we found a prefixed version of the method, return it + } + // found as non-native, so prefix is good, add it, probably just need more prefixes + name_len = trial_len; + name_str = trial_name_str; + } +#endif // INCLUDE_JVMTI + return NULL; // not found +} + void SystemDictionary::resolve_well_known_classes(TRAPS) { assert(WK_KLASS(Object_klass) == NULL, "well-known classes should only be initialized once"); @@ -1976,6 +2055,15 @@ resolve_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK); } + assert(WK_KLASS(Object_klass) != NULL, "well-known classes should now be initialized"); + + // Register native methods of Object + register_native(Object_klass(), vmSymbols::hashCode_name(), vmSymbols::void_int_signature(), (address)&JVM_IHashCode, THREAD); + register_native(Object_klass(), vmSymbols::wait_name(), vmSymbols::long_void_signature(), (address)&JVM_MonitorWait, THREAD); + register_native(Object_klass(), vmSymbols::notify_name(), vmSymbols::void_method_signature(), (address)&JVM_MonitorNotify, THREAD); + register_native(Object_klass(), vmSymbols::notifyAll_name(), vmSymbols::void_method_signature(), (address)&JVM_MonitorNotifyAll, THREAD); + register_native(Object_klass(), vmSymbols::clone_name(), vmSymbols::void_object_signature(), (address)&JVM_Clone, THREAD); + // Calculate offsets for String and Class classes since they are loaded and // can be used after this point. java_lang_String::compute_offsets();