diff src/share/vm/prims/jvm.cpp @ 20677:fe34c5ab0b35

8042235: redefining method used by multiple MethodHandles crashes VM Summary: note all MemberNames created on internal list for adjusting method entries. Reviewed-by: sspitsyn, dcubed, lfoltan
author coleenp
date Wed, 19 Nov 2014 13:02:11 -0500
parents 4cb90023bf2b
children d4caf9c96afd
line wrap: on
line diff
--- a/src/share/vm/prims/jvm.cpp	Thu Nov 20 11:06:26 2014 +0100
+++ b/src/share/vm/prims/jvm.cpp	Wed Nov 19 13:02:11 2014 -0500
@@ -603,13 +603,14 @@
 
   // Make shallow object copy
   const int size = obj->size();
-  oop new_obj = NULL;
+  oop new_obj_oop = NULL;
   if (obj->is_array()) {
     const int length = ((arrayOop)obj())->length();
-    new_obj = CollectedHeap::array_allocate(klass, size, length, CHECK_NULL);
+    new_obj_oop = CollectedHeap::array_allocate(klass, size, length, CHECK_NULL);
   } else {
-    new_obj = CollectedHeap::obj_allocate(klass, size, CHECK_NULL);
+    new_obj_oop = CollectedHeap::obj_allocate(klass, size, CHECK_NULL);
   }
+
   // 4839641 (4840070): We must do an oop-atomic copy, because if another thread
   // is modifying a reference field in the clonee, a non-oop-atomic copy might
   // be suspended in the middle of copying the pointer and end up with parts
@@ -620,24 +621,41 @@
   // The same is true of StubRoutines::object_copy and the various oop_copy
   // variants, and of the code generated by the inline_native_clone intrinsic.
   assert(MinObjAlignmentInBytes >= BytesPerLong, "objects misaligned");
-  Copy::conjoint_jlongs_atomic((jlong*)obj(), (jlong*)new_obj,
+  Copy::conjoint_jlongs_atomic((jlong*)obj(), (jlong*)new_obj_oop,
                                (size_t)align_object_size(size) / HeapWordsPerLong);
   // Clear the header
-  new_obj->init_mark();
+  new_obj_oop->init_mark();
 
   // Store check (mark entire object and let gc sort it out)
   BarrierSet* bs = Universe::heap()->barrier_set();
   assert(bs->has_write_region_opt(), "Barrier set does not have write_region");
-  bs->write_region(MemRegion((HeapWord*)new_obj, size));
+  bs->write_region(MemRegion((HeapWord*)new_obj_oop, size));
+
+  Handle new_obj(THREAD, new_obj_oop);
+  // Special handling for MemberNames.  Since they contain Method* metadata, they
+  // must be registered so that RedefineClasses can fix metadata contained in them.
+  if (java_lang_invoke_MemberName::is_instance(new_obj()) &&
+      java_lang_invoke_MemberName::is_method(new_obj())) {
+    Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(new_obj());
+    // MemberName may be unresolved, so doesn't need registration until resolved.
+    if (method != NULL) {
+      methodHandle m(THREAD, method);
+      // This can safepoint and redefine method, so need both new_obj and method
+      // in a handle, for two different reasons.  new_obj can move, method can be
+      // deleted if nothing is using it on the stack.
+      m->method_holder()->add_member_name(new_obj());
+    }
+  }
 
   // Caution: this involves a java upcall, so the clone should be
   // "gc-robust" by this stage.
   if (klass->has_finalizer()) {
     assert(obj->is_instance(), "should be instanceOop");
-    new_obj = InstanceKlass::register_finalizer(instanceOop(new_obj), CHECK_NULL);
+    new_obj_oop = InstanceKlass::register_finalizer(instanceOop(new_obj()), CHECK_NULL);
+    new_obj = Handle(THREAD, new_obj_oop);
   }
 
-  return JNIHandles::make_local(env, oop(new_obj));
+  return JNIHandles::make_local(env, new_obj());
 JVM_END
 
 // java.lang.Compiler ////////////////////////////////////////////////////