8078725: method adjustments can be done just once for all classes involved into redefinition
Walk all classes at the end of redefinition and adjust method entries and clean MethodData Reviewed-by: sspitsyn
This commit is contained in:
parent
b88c7ac223
commit
351280bbb8
@ -591,7 +591,7 @@ void ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
|
||||
|
||||
// a constant pool cache entry should never contain old or obsolete methods
|
||||
bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() {
|
||||
Method* m = get_interesting_method_entry(NULL);
|
||||
Method* m = get_interesting_method_entry();
|
||||
// return false if m refers to a non-deleted old or obsolete method
|
||||
if (m != NULL) {
|
||||
assert(m->is_valid() && m->is_method(), "m is a valid method");
|
||||
@ -601,7 +601,7 @@ bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() {
|
||||
}
|
||||
}
|
||||
|
||||
Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) {
|
||||
Method* ConstantPoolCacheEntry::get_interesting_method_entry() {
|
||||
if (!is_method_entry()) {
|
||||
// not a method entry so not interesting by default
|
||||
return NULL;
|
||||
@ -622,12 +622,9 @@ Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) {
|
||||
}
|
||||
}
|
||||
assert(m != NULL && m->is_method(), "sanity check");
|
||||
if (m == NULL || !m->is_method() || (k != NULL && m->method_holder() != k)) {
|
||||
// robustness for above sanity checks or method is not in
|
||||
// the interesting class
|
||||
if (m == NULL || !m->is_method()) {
|
||||
return NULL;
|
||||
}
|
||||
// the method is in the interesting class so the entry is interesting
|
||||
return m;
|
||||
}
|
||||
#endif // INCLUDE_JVMTI
|
||||
@ -777,10 +774,10 @@ void ConstantPoolCache::set_archived_references(oop o) {
|
||||
// RedefineClasses() API support:
|
||||
// If any entry of this ConstantPoolCache points to any of
|
||||
// old_methods, replace it with the corresponding new_method.
|
||||
void ConstantPoolCache::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
|
||||
void ConstantPoolCache::adjust_method_entries(bool * trace_name_printed) {
|
||||
for (int i = 0; i < length(); i++) {
|
||||
ConstantPoolCacheEntry* entry = entry_at(i);
|
||||
Method* old_method = entry->get_interesting_method_entry(holder);
|
||||
Method* old_method = entry->get_interesting_method_entry();
|
||||
if (old_method == NULL || !old_method->is_old()) {
|
||||
continue; // skip uninteresting entries
|
||||
}
|
||||
@ -789,11 +786,7 @@ void ConstantPoolCache::adjust_method_entries(InstanceKlass* holder, bool * trac
|
||||
entry->initialize_entry(entry->constant_pool_index());
|
||||
continue;
|
||||
}
|
||||
Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
|
||||
|
||||
assert(new_method != NULL, "method_with_idnum() should not be NULL");
|
||||
assert(old_method != new_method, "sanity check");
|
||||
|
||||
Method* new_method = old_method->get_new_method();
|
||||
entry_at(i)->adjust_method_entry(old_method, new_method, trace_name_printed);
|
||||
}
|
||||
}
|
||||
@ -801,7 +794,7 @@ void ConstantPoolCache::adjust_method_entries(InstanceKlass* holder, bool * trac
|
||||
// the constant pool cache should never contain old or obsolete methods
|
||||
bool ConstantPoolCache::check_no_old_or_obsolete_entries() {
|
||||
for (int i = 1; i < length(); i++) {
|
||||
if (entry_at(i)->get_interesting_method_entry(NULL) != NULL &&
|
||||
if (entry_at(i)->get_interesting_method_entry() != NULL &&
|
||||
!entry_at(i)->check_no_old_or_obsolete_entries()) {
|
||||
return false;
|
||||
}
|
||||
@ -811,7 +804,7 @@ bool ConstantPoolCache::check_no_old_or_obsolete_entries() {
|
||||
|
||||
void ConstantPoolCache::dump_cache() {
|
||||
for (int i = 1; i < length(); i++) {
|
||||
if (entry_at(i)->get_interesting_method_entry(NULL) != NULL) {
|
||||
if (entry_at(i)->get_interesting_method_entry() != NULL) {
|
||||
entry_at(i)->print(tty, i);
|
||||
}
|
||||
}
|
||||
|
@ -376,7 +376,7 @@ class ConstantPoolCacheEntry {
|
||||
void adjust_method_entry(Method* old_method, Method* new_method,
|
||||
bool* trace_name_printed);
|
||||
bool check_no_old_or_obsolete_entries();
|
||||
Method* get_interesting_method_entry(Klass* k);
|
||||
Method* get_interesting_method_entry();
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
// Debugging & Printing
|
||||
@ -496,7 +496,7 @@ class ConstantPoolCache: public MetaspaceObj {
|
||||
// trace_name_printed is set to true if the current call has
|
||||
// printed the klass name so that other routines in the adjust_*
|
||||
// group don't print the klass name.
|
||||
void adjust_method_entries(InstanceKlass* holder, bool* trace_name_printed);
|
||||
void adjust_method_entries(bool* trace_name_printed);
|
||||
bool check_no_old_or_obsolete_entries();
|
||||
void dump_cache();
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
@ -2917,22 +2917,18 @@ Method* InstanceKlass::method_at_itable(Klass* holder, int index, TRAPS) {
|
||||
// not yet in the vtable due to concurrent subclass define and superinterface
|
||||
// redefinition
|
||||
// Note: those in the vtable, should have been updated via adjust_method_entries
|
||||
void InstanceKlass::adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed) {
|
||||
void InstanceKlass::adjust_default_methods(bool* trace_name_printed) {
|
||||
// search the default_methods for uses of either obsolete or EMCP methods
|
||||
if (default_methods() != NULL) {
|
||||
for (int index = 0; index < default_methods()->length(); index ++) {
|
||||
Method* old_method = default_methods()->at(index);
|
||||
if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
|
||||
if (old_method == NULL || !old_method->is_old()) {
|
||||
continue; // skip uninteresting entries
|
||||
}
|
||||
assert(!old_method->is_deleted(), "default methods may not be deleted");
|
||||
|
||||
Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
|
||||
|
||||
assert(new_method != NULL, "method_with_idnum() should not be NULL");
|
||||
assert(old_method != new_method, "sanity check");
|
||||
|
||||
Method* new_method = old_method->get_new_method();
|
||||
default_methods()->at_put(index, new_method);
|
||||
|
||||
if (log_is_enabled(Info, redefine, class, update)) {
|
||||
ResourceMark rm;
|
||||
if (!(*trace_name_printed)) {
|
||||
|
@ -1141,7 +1141,7 @@ public:
|
||||
Method* method_at_itable(Klass* holder, int index, TRAPS);
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
void adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed);
|
||||
void adjust_default_methods(bool* trace_name_printed);
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
void clean_weak_instanceklass_links();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -942,21 +942,18 @@ bool klassVtable::adjust_default_method(int vtable_index, Method* old_method, Me
|
||||
}
|
||||
|
||||
// search the vtable for uses of either obsolete or EMCP methods
|
||||
void klassVtable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
|
||||
void klassVtable::adjust_method_entries(bool * trace_name_printed) {
|
||||
int prn_enabled = 0;
|
||||
for (int index = 0; index < length(); index++) {
|
||||
Method* old_method = unchecked_method_at(index);
|
||||
if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
|
||||
if (old_method == NULL || !old_method->is_old()) {
|
||||
continue; // skip uninteresting entries
|
||||
}
|
||||
assert(!old_method->is_deleted(), "vtable methods may not be deleted");
|
||||
|
||||
Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
|
||||
|
||||
assert(new_method != NULL, "method_with_idnum() should not be NULL");
|
||||
assert(old_method != new_method, "sanity check");
|
||||
|
||||
Method* new_method = old_method->get_new_method();
|
||||
put_method_at(new_method, index);
|
||||
|
||||
// For default methods, need to update the _default_methods array
|
||||
// which can only have one method entry for a given signature
|
||||
bool updated_default = false;
|
||||
@ -1272,21 +1269,16 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Insta
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
// search the itable for uses of either obsolete or EMCP methods
|
||||
void klassItable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
|
||||
void klassItable::adjust_method_entries(bool * trace_name_printed) {
|
||||
|
||||
itableMethodEntry* ime = method_entry(0);
|
||||
for (int i = 0; i < _size_method_table; i++, ime++) {
|
||||
Method* old_method = ime->method();
|
||||
if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
|
||||
if (old_method == NULL || !old_method->is_old()) {
|
||||
continue; // skip uninteresting entries
|
||||
}
|
||||
assert(!old_method->is_deleted(), "itable methods may not be deleted");
|
||||
|
||||
Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
|
||||
|
||||
assert(new_method != NULL, "method_with_idnum() should not be NULL");
|
||||
assert(old_method != new_method, "sanity check");
|
||||
|
||||
Method* new_method = old_method->get_new_method();
|
||||
ime->initialize(new_method);
|
||||
|
||||
if (log_is_enabled(Info, redefine, class, update)) {
|
||||
|
@ -103,7 +103,7 @@ class klassVtable {
|
||||
// printed the klass name so that other routines in the adjust_*
|
||||
// group don't print the klass name.
|
||||
bool adjust_default_method(int vtable_index, Method* old_method, Method* new_method);
|
||||
void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed);
|
||||
void adjust_method_entries(bool* trace_name_printed);
|
||||
bool check_no_old_or_obsolete_entries();
|
||||
void dump_vtable();
|
||||
#endif // INCLUDE_JVMTI
|
||||
@ -322,7 +322,7 @@ class klassItable {
|
||||
// trace_name_printed is set to true if the current call has
|
||||
// printed the klass name so that other routines in the adjust_*
|
||||
// group don't print the klass name.
|
||||
void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed);
|
||||
void adjust_method_entries(bool* trace_name_printed);
|
||||
bool check_no_old_or_obsolete_entries();
|
||||
void dump_itable();
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
@ -974,6 +974,15 @@ class Method : public Metadata {
|
||||
// Deallocation function for redefine classes or if an error occurs
|
||||
void deallocate_contents(ClassLoaderData* loader_data);
|
||||
|
||||
Method* get_new_method() const {
|
||||
InstanceKlass* holder = method_holder();
|
||||
Method* new_method = holder->method_with_idnum(orig_method_idnum());
|
||||
|
||||
assert(new_method != NULL, "method_with_idnum() should not be NULL");
|
||||
assert(this != new_method, "sanity check");
|
||||
return new_method;
|
||||
}
|
||||
|
||||
// Printing
|
||||
#ifndef PRODUCT
|
||||
void print_on(outputStream* st) const;
|
||||
|
@ -62,10 +62,11 @@ Method** VM_RedefineClasses::_matching_old_methods = NULL;
|
||||
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 @@ VM_RedefineClasses::VM_RedefineClasses(jint class_count,
|
||||
_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 @@ void VM_RedefineClasses::doit() {
|
||||
// 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 @@ void VM_RedefineClasses::set_new_constant_pool(
|
||||
// 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<Method*>* 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 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
|
||||
// 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 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
|
||||
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 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
|
||||
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<Method*>* 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 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
|
||||
|
||||
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 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
|
||||
_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.
|
||||
|
@ -338,20 +338,22 @@ struct JvmtiCachedClassFileData {
|
||||
class VM_RedefineClasses: public VM_Operation {
|
||||
private:
|
||||
// These static fields are needed by ClassLoaderDataGraph::classes_do()
|
||||
// facility and the AdjustCpoolCacheAndVtable helper:
|
||||
// facility and the CheckClass and AdjustAndCleanMetadata helpers.
|
||||
static Array<Method*>* _old_methods;
|
||||
static Array<Method*>* _new_methods;
|
||||
static Method** _matching_old_methods;
|
||||
static Method** _matching_new_methods;
|
||||
static Method** _deleted_methods;
|
||||
static Method** _added_methods;
|
||||
static Method** _matching_old_methods;
|
||||
static Method** _matching_new_methods;
|
||||
static Method** _deleted_methods;
|
||||
static Method** _added_methods;
|
||||
static int _matching_methods_length;
|
||||
static int _deleted_methods_length;
|
||||
static int _added_methods_length;
|
||||
static Klass* _the_class;
|
||||
static bool _has_redefined_Object;
|
||||
static bool _has_null_class_loader;
|
||||
|
||||
// The instance fields are used to pass information from
|
||||
// doit_prologue() to doit() and doit_epilogue().
|
||||
Klass* _the_class;
|
||||
jint _class_count;
|
||||
const jvmtiClassDefinition *_class_defs; // ptr to _class_count defs
|
||||
|
||||
@ -513,20 +515,14 @@ class VM_RedefineClasses: public VM_Operation {
|
||||
// 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.
|
||||
class AdjustCpoolCacheAndVtable : public KlassClosure {
|
||||
// to fix up these pointers and clean MethodData out.
|
||||
class AdjustAndCleanMetadata : public KlassClosure {
|
||||
Thread* _thread;
|
||||
public:
|
||||
AdjustCpoolCacheAndVtable(Thread* t) : _thread(t) {}
|
||||
AdjustAndCleanMetadata(Thread* t) : _thread(t) {}
|
||||
void do_klass(Klass* k);
|
||||
};
|
||||
|
||||
// Clean MethodData out
|
||||
class MethodDataCleaner : public KlassClosure {
|
||||
public:
|
||||
MethodDataCleaner() {}
|
||||
void do_klass(Klass* k);
|
||||
};
|
||||
public:
|
||||
VM_RedefineClasses(jint class_count,
|
||||
const jvmtiClassDefinition *class_defs,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -232,12 +232,7 @@ void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
InstanceKlass* holder = old_method->method_holder();
|
||||
Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
|
||||
assert(holder == new_method->method_holder(), "call after swapping redefined guts");
|
||||
assert(new_method != NULL, "method_with_idnum() should not be NULL");
|
||||
assert(old_method != new_method, "sanity check");
|
||||
|
||||
Method* new_method = old_method->get_new_method();
|
||||
java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, new_method);
|
||||
|
||||
ResourceMark rm;
|
||||
|
Loading…
Reference in New Issue
Block a user