changeset 3627:2a48c84f1d04

7197269: NPG: FollowReferences has no ClassLoader -> Class link to follow Summary: restore java/lang/ClassLoader.addClass() upcall Reviewed-by: sspitsyn, dcubed, jmasa
author coleenp
date Mon, 17 Sep 2012 10:46:59 -0400
parents 859cd1a76f8a
children 9646b7ff4d14
files src/share/vm/classfile/systemDictionary.cpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/memory/universe.cpp src/share/vm/memory/universe.hpp
diffstat 4 files changed, 29 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/classfile/systemDictionary.cpp	Thu Sep 13 21:20:26 2012 +0200
+++ b/src/share/vm/classfile/systemDictionary.cpp	Mon Sep 17 10:46:59 2012 -0400
@@ -1496,6 +1496,19 @@
   int d_index = dictionary()->hash_to_index(d_hash);
   check_constraints(d_index, d_hash, k, class_loader_h, true, CHECK);
 
+  // Register class just loaded with class loader (placed in Vector)
+  // Note we do this before updating the dictionary, as this can
+  // fail with an OutOfMemoryError (if it does, we will *not* put this
+  // class in the dictionary and will not update the class hierarchy).
+  // JVMTI FollowReferences needs to find the classes this way.
+  if (k->class_loader() != NULL) {
+    methodHandle m(THREAD, Universe::loader_addClass_method());
+    JavaValue result(T_VOID);
+    JavaCallArguments args(class_loader_h);
+    args.push_oop(Handle(THREAD, k->java_mirror()));
+    JavaCalls::call(&result, m, &args, CHECK);
+  }
+
   // Add the new class. We need recompile lock during update of CHA.
   {
     unsigned int p_hash = placeholders()->compute_hash(name_h, loader_data);
--- a/src/share/vm/classfile/vmSymbols.hpp	Thu Sep 13 21:20:26 2012 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Sep 17 10:46:59 2012 -0400
@@ -314,6 +314,7 @@
   template(type_name,                                 "type")                                     \
   template(findNative_name,                           "findNative")                               \
   template(deadChild_name,                            "deadChild")                                \
+  template(addClass_name,                             "addClass")                                 \
   template(getFromClass_name,                         "getFromClass")                             \
   template(dispatch_name,                             "dispatch")                                 \
   template(getSystemClassLoader_name,                 "getSystemClassLoader")                     \
--- a/src/share/vm/memory/universe.cpp	Thu Sep 13 21:20:26 2012 +0200
+++ b/src/share/vm/memory/universe.cpp	Mon Sep 17 10:46:59 2012 -0400
@@ -117,6 +117,7 @@
 oop Universe::_the_null_string                        = NULL;
 oop Universe::_the_min_jint_string                   = NULL;
 LatestMethodOopCache* Universe::_finalizer_register_cache = NULL;
+LatestMethodOopCache* Universe::_loader_addClass_cache    = NULL;
 ActiveMethodOopsCache* Universe::_reflect_invoke_cache    = NULL;
 oop Universe::_out_of_memory_error_java_heap          = NULL;
 oop Universe::_out_of_memory_error_perm_gen           = NULL;
@@ -228,6 +229,7 @@
   f->do_ptr((void**)&_the_empty_method_array);
   f->do_ptr((void**)&_the_empty_klass_array);
   _finalizer_register_cache->serialize(f);
+  _loader_addClass_cache->serialize(f);
   _reflect_invoke_cache->serialize(f);
 }
 
@@ -652,6 +654,7 @@
   // We have a heap so create the Method* caches before
   // Metaspace::initialize_shared_spaces() tries to populate them.
   Universe::_finalizer_register_cache = new LatestMethodOopCache();
+  Universe::_loader_addClass_cache    = new LatestMethodOopCache();
   Universe::_reflect_invoke_cache     = new ActiveMethodOopsCache();
 
   if (UseSharedSpaces) {
@@ -1041,6 +1044,16 @@
   }
   Universe::_reflect_invoke_cache->init(k_h(), m, CHECK_false);
 
+  // Setup method for registering loaded classes in class loader vector
+  InstanceKlass::cast(SystemDictionary::ClassLoader_klass())->link_class(CHECK_false);
+  m = InstanceKlass::cast(SystemDictionary::ClassLoader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature());
+  if (m == NULL || m->is_static()) {
+    THROW_MSG_(vmSymbols::java_lang_NoSuchMethodException(),
+      "java.lang.ClassLoader.addClass", false);
+  }
+  Universe::_loader_addClass_cache->init(
+    SystemDictionary::ClassLoader_klass(), m, CHECK_false);
+
   // The folowing is initializing converter functions for serialization in
   // JVM.cpp. If we clean up the StrictMath code above we may want to find
   // a better solution for this as well.
--- a/src/share/vm/memory/universe.hpp	Thu Sep 13 21:20:26 2012 +0200
+++ b/src/share/vm/memory/universe.hpp	Mon Sep 17 10:46:59 2012 -0400
@@ -175,6 +175,7 @@
   static oop          _the_null_string;               // A cache of "null" as a Java string
   static oop          _the_min_jint_string;          // A cache of "-2147483648" as a Java string
   static LatestMethodOopCache* _finalizer_register_cache; // static method for registering finalizable objects
+  static LatestMethodOopCache* _loader_addClass_cache;    // method for registering loaded classes in class loader vector
   static ActiveMethodOopsCache* _reflect_invoke_cache;    // method for security checks
   static oop          _out_of_memory_error_java_heap; // preallocated error object (no backtrace)
   static oop          _out_of_memory_error_perm_gen;  // preallocated error object (no backtrace)
@@ -318,6 +319,7 @@
   static oop          the_null_string()               { return _the_null_string;               }
   static oop          the_min_jint_string()          { return _the_min_jint_string;          }
   static Method*      finalizer_register_method()     { return _finalizer_register_cache->get_Method(); }
+  static Method*      loader_addClass_method()        { return _loader_addClass_cache->get_Method(); }
   static ActiveMethodOopsCache* reflect_invoke_cache() { return _reflect_invoke_cache; }
   static oop          null_ptr_exception_instance()   { return _null_ptr_exception_instance;   }
   static oop          arithmetic_exception_instance() { return _arithmetic_exception_instance; }