diff -r 68bbd727dd5f -r 9c3fe09f69bc src/hotspot/share/prims/jvmtiRedefineClasses.cpp --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp Fri Feb 22 11:07:18 2019 -0800 +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp Fri Feb 22 13:56:08 2019 -0500 @@ -62,10 +62,11 @@ Method** VM_RedefineClasses::_matching_new_methods = NULL; Method** VM_RedefineClasses::_deleted_methods = NULL; Method** VM_RedefineClasses::_added_methods = NULL; -int VM_RedefineClasses::_matching_methods_length = 0; -int VM_RedefineClasses::_deleted_methods_length = 0; -int VM_RedefineClasses::_added_methods_length = 0; -Klass* VM_RedefineClasses::_the_class = NULL; +int VM_RedefineClasses::_matching_methods_length = 0; +int VM_RedefineClasses::_deleted_methods_length = 0; +int VM_RedefineClasses::_added_methods_length = 0; +bool VM_RedefineClasses::_has_redefined_Object = false; +bool VM_RedefineClasses::_has_null_class_loader = false; VM_RedefineClasses::VM_RedefineClasses(jint class_count, @@ -76,6 +77,9 @@ _class_load_kind = class_load_kind; _any_class_has_resolved_methods = false; _res = JVMTI_ERROR_NONE; + _the_class = NULL; + _has_redefined_Object = false; + _has_null_class_loader = false; } static inline InstanceKlass* get_ik(jclass def) { @@ -214,11 +218,12 @@ // Flush all compiled code that depends on the classes redefined. flush_dependent_code(); - // Clean out MethodData pointing to old Method* + // Adjust constantpool caches and vtables for all classes + // that reference methods of the evolved classes. // Have to do this after all classes are redefined and all methods that // are redefined are marked as old. - MethodDataCleaner clean_weak_method_links; - ClassLoaderDataGraph::classes_do(&clean_weak_method_links); + AdjustAndCleanMetadata adjust_and_clean_metadata(thread); + ClassLoaderDataGraph::classes_do(&adjust_and_clean_metadata); // JSR-292 support if (_any_class_has_resolved_methods) { @@ -3415,25 +3420,35 @@ // Unevolving classes may point to methods of the_class directly // from their constant pool caches, itables, and/or vtables. We // use the ClassLoaderDataGraph::classes_do() facility and this helper -// to fix up these pointers. +// to fix up these pointers. MethodData also points to old methods and +// must be cleaned. // Adjust cpools and vtables closure -void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { +void VM_RedefineClasses::AdjustAndCleanMetadata::do_klass(Klass* k) { // This is a very busy routine. We don't want too much tracing // printed out. bool trace_name_printed = false; - InstanceKlass *the_class = InstanceKlass::cast(_the_class); // If the class being redefined is java.lang.Object, we need to fix all // array class vtables also - if (k->is_array_klass() && _the_class == SystemDictionary::Object_klass()) { - k->vtable().adjust_method_entries(the_class, &trace_name_printed); + if (k->is_array_klass() && _has_redefined_Object) { + k->vtable().adjust_method_entries(&trace_name_printed); } else if (k->is_instance_klass()) { HandleMark hm(_thread); InstanceKlass *ik = InstanceKlass::cast(k); + // Clean MethodData of this class's methods so they don't refer to + // old methods that are no longer running. + Array* methods = ik->methods(); + int num_methods = methods->length(); + for (int index = 0; index < num_methods; ++index) { + if (methods->at(index)->method_data() != NULL) { + methods->at(index)->method_data()->clean_weak_method_links(); + } + } + // HotSpot specific optimization! HotSpot does not currently // support delegation from the bootstrap class loader to a // user-defined class loader. This means that if the bootstrap @@ -3446,57 +3461,29 @@ // If the current class being redefined has a user-defined class // loader as its defining class loader, then we can skip all // classes loaded by the bootstrap class loader. - bool is_user_defined = (_the_class->class_loader() != NULL); - if (is_user_defined && ik->class_loader() == NULL) { + if (!_has_null_class_loader && ik->class_loader() == NULL) { return; } - // Fix the vtable embedded in the_class and subclasses of the_class, - // if one exists. We discard scratch_class and we don't keep an - // InstanceKlass around to hold obsolete methods so we don't have - // any other InstanceKlass embedded vtables to update. The vtable - // holds the Method*s for virtual (but not final) methods. - // Default methods, or concrete methods in interfaces are stored - // in the vtable, so if an interface changes we need to check - // adjust_method_entries() for every InstanceKlass, which will also - // adjust the default method vtable indices. - // We also need to adjust any default method entries that are - // not yet in the vtable, because the vtable setup is in progress. - // This must be done after we adjust the default_methods and - // default_vtable_indices for methods already in the vtable. - // If redefining Unsafe, walk all the vtables looking for entries. - if (ik->vtable_length() > 0 && (_the_class->is_interface() - || _the_class == SystemDictionary::internal_Unsafe_klass() - || ik->is_subtype_of(_the_class))) { - // ik->vtable() creates a wrapper object; rm cleans it up - ResourceMark rm(_thread); - - ik->vtable().adjust_method_entries(the_class, &trace_name_printed); - ik->adjust_default_methods(the_class, &trace_name_printed); + // Adjust all vtables, default methods and itables, to clean out old methods. + ResourceMark rm(_thread); + if (ik->vtable_length() > 0) { + ik->vtable().adjust_method_entries(&trace_name_printed); + ik->adjust_default_methods(&trace_name_printed); } - // If the current class has an itable and we are either redefining an - // interface or if the current class is a subclass of the_class, then - // we potentially have to fix the itable. If we are redefining an - // interface, then we have to call adjust_method_entries() for - // every InstanceKlass that has an itable since there isn't a - // subclass relationship between an interface and an InstanceKlass. - // If redefining Unsafe, walk all the itables looking for entries. - if (ik->itable_length() > 0 && (_the_class->is_interface() - || _the_class == SystemDictionary::internal_Unsafe_klass() - || ik->is_subclass_of(_the_class))) { - ResourceMark rm(_thread); - ik->itable().adjust_method_entries(the_class, &trace_name_printed); + if (ik->itable_length() > 0) { + ik->itable().adjust_method_entries(&trace_name_printed); } // The constant pools in other classes (other_cp) can refer to - // methods in the_class. We have to update method information in + // old methods. We have to update method information in // other_cp's cache. If other_cp has a previous version, then we // have to repeat the process for each previous version. The // constant pool cache holds the Method*s for non-virtual // methods and for virtual, final methods. // - // Special case: if the current class is the_class, then new_cp + // Special case: if the current class being redefined, then new_cp // has already been attached to the_class and old_cp has already // been added as a previous version. The new_cp doesn't have any // cached references to old methods so it doesn't need to be @@ -3505,12 +3492,12 @@ constantPoolHandle other_cp; ConstantPoolCache* cp_cache; - if (ik != _the_class) { + if (!ik->is_being_redefined()) { // this klass' constant pool cache may need adjustment other_cp = constantPoolHandle(ik->constants()); cp_cache = other_cp->cache(); if (cp_cache != NULL) { - cp_cache->adjust_method_entries(the_class, &trace_name_printed); + cp_cache->adjust_method_entries(&trace_name_printed); } } @@ -3520,23 +3507,7 @@ pv_node = pv_node->previous_versions()) { cp_cache = pv_node->constants()->cache(); if (cp_cache != NULL) { - cp_cache->adjust_method_entries(pv_node, &trace_name_printed); - } - } - } -} - -// Clean method data for this class -void VM_RedefineClasses::MethodDataCleaner::do_klass(Klass* k) { - if (k->is_instance_klass()) { - InstanceKlass *ik = InstanceKlass::cast(k); - // Clean MethodData of this class's methods so they don't refer to - // old methods that are no longer running. - Array* methods = ik->methods(); - int num_methods = methods->length(); - for (int index = 0; index < num_methods; ++index) { - if (methods->at(index)->method_data() != NULL) { - methods->at(index)->method_data()->clean_weak_method_links(); + cp_cache->adjust_method_entries(&trace_name_printed); } } } @@ -3972,6 +3943,10 @@ InstanceKlass* the_class = get_ik(the_jclass); + // Set some flags to control and optimize adjusting method entries + _has_redefined_Object |= the_class == SystemDictionary::Object_klass(); + _has_null_class_loader |= the_class->class_loader() == NULL; + // Remove all breakpoints in methods of this class JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); jvmti_breakpoints.clearall_in_class_at_safepoint(the_class); @@ -4193,11 +4168,6 @@ _timer_rsc_phase2.start(); } - // Adjust constantpool caches and vtables for all classes - // that reference methods of the evolved class. - AdjustCpoolCacheAndVtable adjust_cpool_cache_and_vtable(THREAD); - ClassLoaderDataGraph::classes_do(&adjust_cpool_cache_and_vtable); - if (the_class->oop_map_cache() != NULL) { // Flush references to any obsolete methods from the oop map cache // so that obsolete methods are not pinned.