< prev index next >

src/hotspot/share/classfile/systemDictionary.cpp

Print this page

        

@@ -1935,10 +1935,89 @@
 
   // move the starting value forward to the limit:
   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");
 
   // Create the ModuleEntry for java.base.  This call needs to be done here,
   // after vmSymbols::initialize() is called but before any classes are pre-loaded.

@@ -1974,10 +2053,19 @@
 #endif
   {
     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();
   java_lang_Class::compute_offsets();
 
< prev index next >