< prev index next >

src/hotspot/share/oops/method.cpp

Print this page
rev 56655 : 8232613: Move Object.registerNatives into HotSpot
Reviewed-by: alanb, coleenp, lfoltan, dholmes, adinn

*** 23,32 **** --- 23,33 ---- */ #include "precompiled.hpp" #include "classfile/classLoaderDataGraph.hpp" #include "classfile/metadataOnStackMark.hpp" + #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" #include "code/debugInfoRec.hpp" #include "compiler/compilationPolicy.hpp" #include "gc/shared/collectedHeap.inline.hpp"
*** 376,386 **** --- 377,464 ---- _vtable_index = itable_index_max - index; } assert(valid_itable_index(), ""); } + // 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. + static Method* 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 + } + + bool Method::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; + } bool Method::was_executed_more_than(int n) { // Invocation counter is reset when the Method* is compiled. // If the method has compiled code we therefore assume it has // be excuted more than n times.
< prev index next >