Tue, 03 Sep 2019 06:57:35 +0100
8155951: VM crash in nsk/jvmti/RedefineClasses/StressRedefine: assert failed: Corrupted constant pool
8151066: assert(0 <= i && i < length()) failed: index out of bounds
Summary: lock classes for redefinition because constant pool merging isn't thread safe, use method constant pool because constant pool merging doesn't make equivalent cpCaches because of invokedynamic
Reviewed-by: shade, andrew
1.1 --- a/src/share/vm/ci/ciStreams.cpp Tue Sep 03 06:41:37 2019 +0100 1.2 +++ b/src/share/vm/ci/ciStreams.cpp Tue Sep 03 06:57:35 2019 +0100 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -361,14 +361,14 @@ 1.11 ciMethod* ciBytecodeStream::get_method(bool& will_link, ciSignature* *declared_signature_result) { 1.12 VM_ENTRY_MARK; 1.13 ciEnv* env = CURRENT_ENV; 1.14 - constantPoolHandle cpool(_method->get_Method()->constants()); 1.15 + constantPoolHandle cpool(THREAD, _method->get_Method()->constants()); 1.16 ciMethod* m = env->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder); 1.17 will_link = m->is_loaded(); 1.18 1.19 // Use the MethodType stored in the CP cache to create a signature 1.20 // with correct types (in respect to class loaders). 1.21 if (has_method_type()) { 1.22 - ciSymbol* sig_sym = env->get_symbol(cpool->symbol_at(get_method_signature_index())); 1.23 + ciSymbol* sig_sym = env->get_symbol(cpool->symbol_at(get_method_signature_index(cpool))); 1.24 ciKlass* pool_holder = env->get_klass(cpool->pool_holder()); 1.25 ciMethodType* method_type = get_method_type(); 1.26 ciSignature* declared_signature = new (env->arena()) ciSignature(pool_holder, sig_sym, method_type); 1.27 @@ -465,9 +465,8 @@ 1.28 // Get the constant pool index of the signature of the method 1.29 // referenced by the current bytecode. Used for generating 1.30 // deoptimization information. 1.31 -int ciBytecodeStream::get_method_signature_index() { 1.32 +int ciBytecodeStream::get_method_signature_index(const constantPoolHandle& cpool) { 1.33 GUARDED_VM_ENTRY( 1.34 - ConstantPool* cpool = _holder->get_instanceKlass()->constants(); 1.35 const int method_index = get_method_index(); 1.36 const int name_and_type_index = cpool->name_and_type_ref_index_at(method_index); 1.37 return cpool->signature_ref_index_at(name_and_type_index);
2.1 --- a/src/share/vm/ci/ciStreams.hpp Tue Sep 03 06:41:37 2019 +0100 2.2 +++ b/src/share/vm/ci/ciStreams.hpp Tue Sep 03 06:57:35 2019 +0100 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -264,7 +264,7 @@ 2.11 ciMethodType* get_method_type(); 2.12 ciKlass* get_declared_method_holder(); 2.13 int get_method_holder_index(); 2.14 - int get_method_signature_index(); 2.15 + int get_method_signature_index(const constantPoolHandle& cpool); 2.16 2.17 // Get the resolved references arrays from the constant pool 2.18 ciObjArray* get_resolved_references();
3.1 --- a/src/share/vm/oops/instanceKlass.hpp Tue Sep 03 06:41:37 2019 +0100 3.2 +++ b/src/share/vm/oops/instanceKlass.hpp Tue Sep 03 06:57:35 2019 +0100 3.3 @@ -225,6 +225,7 @@ 3.4 // _is_marked_dependent can be set concurrently, thus cannot be part of the 3.5 // _misc_flags. 3.6 bool _is_marked_dependent; // used for marking during flushing and deoptimization 3.7 + bool _is_being_redefined; // used for locking redefinition 3.8 bool _has_unloaded_dependent; 3.9 3.10 enum { 3.11 @@ -667,6 +668,10 @@ 3.12 _nonstatic_oop_map_size = words; 3.13 } 3.14 3.15 + // Redefinition locking. Class can only be redefined by one thread at a time. 3.16 + bool is_being_redefined() const { return _is_being_redefined; } 3.17 + void set_is_being_redefined(bool value) { _is_being_redefined = value; } 3.18 + 3.19 // RedefineClasses() support for previous versions: 3.20 void add_previous_version(instanceKlassHandle ikh, int emcp_method_count); 3.21
4.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue Sep 03 06:41:37 2019 +0100 4.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue Sep 03 06:57:35 2019 +0100 4.3 @@ -67,6 +67,43 @@ 4.4 _res = JVMTI_ERROR_NONE; 4.5 } 4.6 4.7 +static inline InstanceKlass* get_ik(jclass def) { 4.8 + oop mirror = JNIHandles::resolve_non_null(def); 4.9 + return InstanceKlass::cast(java_lang_Class::as_Klass(mirror)); 4.10 +} 4.11 + 4.12 +// If any of the classes are being redefined, wait 4.13 +// Parallel constant pool merging leads to indeterminate constant pools. 4.14 +void VM_RedefineClasses::lock_classes() { 4.15 + MutexLocker ml(RedefineClasses_lock); 4.16 + bool has_redefined; 4.17 + do { 4.18 + has_redefined = false; 4.19 + // Go through classes each time until none are being redefined. 4.20 + for (int i = 0; i < _class_count; i++) { 4.21 + if (get_ik(_class_defs[i].klass)->is_being_redefined()) { 4.22 + RedefineClasses_lock->wait(); 4.23 + has_redefined = true; 4.24 + break; // for loop 4.25 + } 4.26 + } 4.27 + } while (has_redefined); 4.28 + for (int i = 0; i < _class_count; i++) { 4.29 + get_ik(_class_defs[i].klass)->set_is_being_redefined(true); 4.30 + } 4.31 + RedefineClasses_lock->notify_all(); 4.32 +} 4.33 + 4.34 +void VM_RedefineClasses::unlock_classes() { 4.35 + MutexLocker ml(RedefineClasses_lock); 4.36 + for (int i = 0; i < _class_count; i++) { 4.37 + assert(get_ik(_class_defs[i].klass)->is_being_redefined(), 4.38 + "should be being redefined to get here"); 4.39 + get_ik(_class_defs[i].klass)->set_is_being_redefined(false); 4.40 + } 4.41 + RedefineClasses_lock->notify_all(); 4.42 +} 4.43 + 4.44 bool VM_RedefineClasses::doit_prologue() { 4.45 if (_class_count == 0) { 4.46 _res = JVMTI_ERROR_NONE; 4.47 @@ -89,12 +126,21 @@ 4.48 _res = JVMTI_ERROR_NULL_POINTER; 4.49 return false; 4.50 } 4.51 + 4.52 + oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass); 4.53 + // classes for primitives and arrays cannot be redefined 4.54 + // check here so following code can assume these classes are InstanceKlass 4.55 + if (!is_modifiable_class(mirror)) { 4.56 + _res = JVMTI_ERROR_UNMODIFIABLE_CLASS; 4.57 + return false; 4.58 + } 4.59 } 4.60 4.61 // Start timer after all the sanity checks; not quite accurate, but 4.62 // better than adding a bunch of stop() calls. 4.63 RC_TIMER_START(_timer_vm_op_prologue); 4.64 4.65 + lock_classes(); 4.66 // We first load new class versions in the prologue, because somewhere down the 4.67 // call chain it is required that the current thread is a Java thread. 4.68 _res = load_new_class_versions(Thread::current()); 4.69 @@ -111,6 +157,7 @@ 4.70 // Free os::malloc allocated memory in load_new_class_version. 4.71 os::free(_scratch_classes); 4.72 RC_TIMER_STOP(_timer_vm_op_prologue); 4.73 + unlock_classes(); 4.74 return false; 4.75 } 4.76 4.77 @@ -170,6 +217,8 @@ 4.78 } 4.79 4.80 void VM_RedefineClasses::doit_epilogue() { 4.81 + unlock_classes(); 4.82 + 4.83 // Free os::malloc allocated memory. 4.84 os::free(_scratch_classes); 4.85 4.86 @@ -961,14 +1010,7 @@ 4.87 // versions are deleted. Constant pools are deallocated while merging 4.88 // constant pools 4.89 HandleMark hm(THREAD); 4.90 - 4.91 - oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass); 4.92 - // classes for primitives cannot be redefined 4.93 - if (!is_modifiable_class(mirror)) { 4.94 - return JVMTI_ERROR_UNMODIFIABLE_CLASS; 4.95 - } 4.96 - Klass* the_class_oop = java_lang_Class::as_Klass(mirror); 4.97 - instanceKlassHandle the_class = instanceKlassHandle(THREAD, the_class_oop); 4.98 + instanceKlassHandle the_class(THREAD, get_ik(_class_defs[i].klass)); 4.99 Symbol* the_class_sym = the_class->name(); 4.100 4.101 // RC_TRACE_WITH_THREAD macro has an embedded ResourceMark 4.102 @@ -3855,22 +3897,19 @@ 4.103 HandleMark hm(THREAD); // make sure handles from this call are freed 4.104 RC_TIMER_START(_timer_rsc_phase1); 4.105 4.106 - instanceKlassHandle scratch_class(scratch_class_oop); 4.107 - 4.108 - oop the_class_mirror = JNIHandles::resolve_non_null(the_jclass); 4.109 - Klass* the_class_oop = java_lang_Class::as_Klass(the_class_mirror); 4.110 - instanceKlassHandle the_class = instanceKlassHandle(THREAD, the_class_oop); 4.111 + instanceKlassHandle scratch_class(THREAD, scratch_class_oop); 4.112 + instanceKlassHandle the_class(THREAD, get_ik(the_jclass)); 4.113 4.114 // Remove all breakpoints in methods of this class 4.115 JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); 4.116 - jvmti_breakpoints.clearall_in_class_at_safepoint(the_class_oop); 4.117 + jvmti_breakpoints.clearall_in_class_at_safepoint(the_class()); 4.118 4.119 // Deoptimize all compiled code that depends on this class 4.120 flush_dependent_code(the_class, THREAD); 4.121 4.122 _old_methods = the_class->methods(); 4.123 _new_methods = scratch_class->methods(); 4.124 - _the_class_oop = the_class_oop; 4.125 + _the_class_oop = the_class(); 4.126 compute_added_deleted_matching_methods(); 4.127 update_jmethod_ids(); 4.128 4.129 @@ -4094,14 +4133,14 @@ 4.130 RC_TRACE_WITH_THREAD(0x00000001, THREAD, 4.131 ("redefined name=%s, count=%d (avail_mem=" UINT64_FORMAT "K)", 4.132 the_class->external_name(), 4.133 - java_lang_Class::classRedefinedCount(the_class_mirror), 4.134 + java_lang_Class::classRedefinedCount(the_class->java_mirror()), 4.135 os::available_memory() >> 10)); 4.136 4.137 { 4.138 ResourceMark rm(THREAD); 4.139 Events::log_redefinition(THREAD, "redefined class name=%s, count=%d", 4.140 the_class->external_name(), 4.141 - java_lang_Class::classRedefinedCount(the_class_mirror)); 4.142 + java_lang_Class::classRedefinedCount(the_class->java_mirror())); 4.143 4.144 } 4.145 RC_TIMER_STOP(_timer_rsc_phase2);
5.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.hpp Tue Sep 03 06:41:37 2019 +0100 5.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.hpp Tue Sep 03 06:57:35 2019 +0100 5.3 @@ -490,6 +490,10 @@ 5.4 5.5 void flush_dependent_code(instanceKlassHandle k_h, TRAPS); 5.6 5.7 + // lock classes to redefine since constant pool merging isn't thread safe. 5.8 + void lock_classes(); 5.9 + void unlock_classes(); 5.10 + 5.11 static void dump_methods(); 5.12 5.13 // Check that there are no old or obsolete methods
6.1 --- a/src/share/vm/runtime/mutexLocker.cpp Tue Sep 03 06:41:37 2019 +0100 6.2 +++ b/src/share/vm/runtime/mutexLocker.cpp Tue Sep 03 06:57:35 2019 +0100 6.3 @@ -125,6 +125,7 @@ 6.4 Mutex* Management_lock = NULL; 6.5 Monitor* Service_lock = NULL; 6.6 Monitor* PeriodicTask_lock = NULL; 6.7 +Monitor* RedefineClasses_lock = NULL; 6.8 6.9 #ifdef INCLUDE_TRACE 6.10 Mutex* JfrStacktrace_lock = NULL; 6.11 @@ -279,6 +280,7 @@ 6.12 def(ProfileVM_lock , Monitor, special, false); // used for profiling of the VMThread 6.13 def(CompileThread_lock , Monitor, nonleaf+5, false ); 6.14 def(PeriodicTask_lock , Monitor, nonleaf+5, true); 6.15 + def(RedefineClasses_lock , Monitor, nonleaf+5, true); 6.16 6.17 #ifdef INCLUDE_TRACE 6.18 def(JfrMsg_lock , Monitor, leaf, true);
7.1 --- a/src/share/vm/runtime/mutexLocker.hpp Tue Sep 03 06:41:37 2019 +0100 7.2 +++ b/src/share/vm/runtime/mutexLocker.hpp Tue Sep 03 06:57:35 2019 +0100 7.3 @@ -141,6 +141,7 @@ 7.4 extern Mutex* Management_lock; // a lock used to serialize JVM management 7.5 extern Monitor* Service_lock; // a lock used for service thread operation 7.6 extern Monitor* PeriodicTask_lock; // protects the periodic task structure 7.7 +extern Monitor* RedefineClasses_lock; // locks classes from parallel redefinition 7.8 7.9 #ifdef INCLUDE_TRACE 7.10 extern Mutex* JfrStacktrace_lock; // used to guard access to the JFR stacktrace table