< 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 >