--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue May 17 03:26:07 2016 -0400
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue May 17 08:51:05 2016 -0400
@@ -69,6 +69,43 @@
_res = JVMTI_ERROR_NONE;
}
+static inline InstanceKlass* get_ik(jclass def) {
+ oop mirror = JNIHandles::resolve_non_null(def);
+ return InstanceKlass::cast(java_lang_Class::as_Klass(mirror));
+}
+
+// If any of the classes are being redefined, wait
+// Parallel constant pool merging leads to indeterminate constant pools.
+void VM_RedefineClasses::lock_classes() {
+ MutexLocker ml(RedefineClasses_lock);
+ bool has_redefined;
+ do {
+ has_redefined = false;
+ // Go through classes each time until none are being redefined.
+ for (int i = 0; i < _class_count; i++) {
+ if (get_ik(_class_defs[i].klass)->is_being_redefined()) {
+ RedefineClasses_lock->wait();
+ has_redefined = true;
+ break; // for loop
+ }
+ }
+ } while (has_redefined);
+ for (int i = 0; i < _class_count; i++) {
+ get_ik(_class_defs[i].klass)->set_is_being_redefined(true);
+ }
+ RedefineClasses_lock->notify_all();
+}
+
+void VM_RedefineClasses::unlock_classes() {
+ MutexLocker ml(RedefineClasses_lock);
+ for (int i = 0; i < _class_count; i++) {
+ assert(get_ik(_class_defs[i].klass)->is_being_redefined(),
+ "should be being redefined to get here");
+ get_ik(_class_defs[i].klass)->set_is_being_redefined(false);
+ }
+ RedefineClasses_lock->notify_all();
+}
+
bool VM_RedefineClasses::doit_prologue() {
if (_class_count == 0) {
_res = JVMTI_ERROR_NONE;
@@ -91,6 +128,14 @@
_res = JVMTI_ERROR_NULL_POINTER;
return false;
}
+
+ oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass);
+ // classes for primitives and arrays cannot be redefined
+ // check here so following code can assume these classes are InstanceKlass
+ if (!is_modifiable_class(mirror)) {
+ _res = JVMTI_ERROR_UNMODIFIABLE_CLASS;
+ return false;
+ }
}
// Start timer after all the sanity checks; not quite accurate, but
@@ -99,6 +144,7 @@
_timer_vm_op_prologue.start();
}
+ lock_classes();
// We first load new class versions in the prologue, because somewhere down the
// call chain it is required that the current thread is a Java thread.
_res = load_new_class_versions(Thread::current());
@@ -115,6 +161,7 @@
// Free os::malloc allocated memory in load_new_class_version.
os::free(_scratch_classes);
_timer_vm_op_prologue.stop();
+ unlock_classes();
return false;
}
@@ -174,6 +221,8 @@
}
void VM_RedefineClasses::doit_epilogue() {
+ unlock_classes();
+
// Free os::malloc allocated memory.
os::free(_scratch_classes);
@@ -959,14 +1008,7 @@
// versions are deleted. Constant pools are deallocated while merging
// constant pools
HandleMark hm(THREAD);
-
- oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass);
- // classes for primitives cannot be redefined
- if (!is_modifiable_class(mirror)) {
- return JVMTI_ERROR_UNMODIFIABLE_CLASS;
- }
- Klass* the_class_oop = java_lang_Class::as_Klass(mirror);
- instanceKlassHandle the_class = instanceKlassHandle(THREAD, the_class_oop);
+ instanceKlassHandle the_class(THREAD, get_ik(_class_defs[i].klass));
Symbol* the_class_sym = the_class->name();
log_debug(redefine, class, load)
@@ -3757,22 +3799,19 @@
_timer_rsc_phase1.start();
}
- instanceKlassHandle scratch_class(scratch_class_oop);
-
- oop the_class_mirror = JNIHandles::resolve_non_null(the_jclass);
- Klass* the_class_oop = java_lang_Class::as_Klass(the_class_mirror);
- instanceKlassHandle the_class = instanceKlassHandle(THREAD, the_class_oop);
+ instanceKlassHandle scratch_class(THREAD, scratch_class_oop);
+ instanceKlassHandle the_class(THREAD, get_ik(the_jclass));
// Remove all breakpoints in methods of this class
JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints();
- jvmti_breakpoints.clearall_in_class_at_safepoint(the_class_oop);
+ jvmti_breakpoints.clearall_in_class_at_safepoint(the_class());
// Deoptimize all compiled code that depends on this class
flush_dependent_code(the_class, THREAD);
_old_methods = the_class->methods();
_new_methods = scratch_class->methods();
- _the_class_oop = the_class_oop;
+ _the_class_oop = the_class();
compute_added_deleted_matching_methods();
update_jmethod_ids();
@@ -4002,10 +4041,10 @@
increment_class_counter((InstanceKlass *)the_class(), THREAD);
log_info(redefine, class, load)
("redefined name=%s, count=%d (avail_mem=" UINT64_FORMAT "K)",
- the_class->external_name(), java_lang_Class::classRedefinedCount(the_class_mirror), os::available_memory() >> 10);
+ the_class->external_name(), java_lang_Class::classRedefinedCount(the_class->java_mirror()), os::available_memory() >> 10);
Events::log_redefinition(THREAD, "redefined class name=%s, count=%d",
the_class->external_name(),
- java_lang_Class::classRedefinedCount(the_class_mirror));
+ java_lang_Class::classRedefinedCount(the_class->java_mirror()));
}
_timer_rsc_phase2.stop();