< prev index next >
src/share/vm/prims/jvmtiRedefineClasses.cpp
Print this page
*** 56,66 ****
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_oop = NULL;
VM_RedefineClasses::VM_RedefineClasses(jint class_count,
const jvmtiClassDefinition *class_defs,
JvmtiClassLoadKind class_load_kind) {
--- 56,66 ----
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;
VM_RedefineClasses::VM_RedefineClasses(jint class_count,
const jvmtiClassDefinition *class_defs,
JvmtiClassLoadKind class_load_kind) {
*** 225,236 ****
unlock_classes();
// Free os::malloc allocated memory.
os::free(_scratch_classes);
! // Reset the_class_oop to null for error printing.
! _the_class_oop = NULL;
if (log_is_enabled(Info, redefine, class, timer)) {
// Used to have separate timers for "doit" and "all", but the timer
// overhead skewed the measurements.
jlong doit_time = _timer_rsc_phase1.milliseconds() +
--- 225,236 ----
unlock_classes();
// Free os::malloc allocated memory.
os::free(_scratch_classes);
! // Reset the_class to null for error printing.
! _the_class = NULL;
if (log_is_enabled(Info, redefine, class, timer)) {
// Used to have separate timers for "doit" and "all", but the timer
// overhead skewed the measurements.
jlong doit_time = _timer_rsc_phase1.milliseconds() +
*** 655,666 ****
_operands_index_map_count = 0;
} // end finalize_operands_merge()
jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
! instanceKlassHandle the_class,
! instanceKlassHandle scratch_class) {
int i;
// Check superclasses, or rather their names, since superclasses themselves can be
// requested to replace.
// Check for NULL superclass first since this might be java.lang.Object
--- 655,666 ----
_operands_index_map_count = 0;
} // end finalize_operands_merge()
jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
! InstanceKlass* the_class,
! InstanceKlass* scratch_class) {
int i;
// Check superclasses, or rather their names, since superclasses themselves can be
// requested to replace.
// Check for NULL superclass first since this might be java.lang.Object
*** 991,1002 ****
jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) {
// For consistency allocate memory using os::malloc wrapper.
! _scratch_classes = (Klass**)
! os::malloc(sizeof(Klass*) * _class_count, mtClass);
if (_scratch_classes == NULL) {
return JVMTI_ERROR_OUT_OF_MEMORY;
}
// Zero initialize the _scratch_classes array.
for (int i = 0; i < _class_count; i++) {
--- 991,1002 ----
jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) {
// For consistency allocate memory using os::malloc wrapper.
! _scratch_classes = (InstanceKlass**)
! os::malloc(sizeof(InstanceKlass*) * _class_count, mtClass);
if (_scratch_classes == NULL) {
return JVMTI_ERROR_OUT_OF_MEMORY;
}
// Zero initialize the _scratch_classes array.
for (int i = 0; i < _class_count; i++) {
*** 1012,1022 ****
for (int i = 0; i < _class_count; i++) {
// Create HandleMark so that any handles created while loading new class
// versions are deleted. Constant pools are deallocated while merging
// constant pools
HandleMark hm(THREAD);
! instanceKlassHandle the_class(THREAD, get_ik(_class_defs[i].klass));
Symbol* the_class_sym = the_class->name();
log_debug(redefine, class, load)
("loading name=%s kind=%d (avail_mem=" UINT64_FORMAT "K)",
the_class->external_name(), _class_load_kind, os::available_memory() >> 10);
--- 1012,1022 ----
for (int i = 0; i < _class_count; i++) {
// Create HandleMark so that any handles created while loading new class
// versions are deleted. Constant pools are deallocated while merging
// constant pools
HandleMark hm(THREAD);
! InstanceKlass* the_class = get_ik(_class_defs[i].klass);
Symbol* the_class_sym = the_class->name();
log_debug(redefine, class, load)
("loading name=%s kind=%d (avail_mem=" UINT64_FORMAT "K)",
the_class->external_name(), _class_load_kind, os::available_memory() >> 10);
*** 1030,1057 ****
Handle the_class_loader(THREAD, the_class->class_loader());
Handle protection_domain(THREAD, the_class->protection_domain());
// Set redefined class handle in JvmtiThreadState class.
// This redefined class is sent to agent event handler for class file
// load hook event.
! state->set_class_being_redefined(&the_class, _class_load_kind);
! Klass* k = SystemDictionary::parse_stream(the_class_sym,
the_class_loader,
protection_domain,
&st,
THREAD);
// Clear class_being_redefined just to be sure.
state->clear_class_being_redefined();
// TODO: if this is retransform, and nothing changed we can skip it
- instanceKlassHandle scratch_class (THREAD, k);
-
// Need to clean up allocated InstanceKlass if there's an error so assign
// the result here. Caller deallocates all the scratch classes in case of
// an error.
! _scratch_classes[i] = k;
if (HAS_PENDING_EXCEPTION) {
Symbol* ex_name = PENDING_EXCEPTION->klass()->name();
log_info(redefine, class, load, exceptions)("parse_stream exception: '%s'", ex_name->as_C_string());
CLEAR_PENDING_EXCEPTION;
--- 1030,1056 ----
Handle the_class_loader(THREAD, the_class->class_loader());
Handle protection_domain(THREAD, the_class->protection_domain());
// Set redefined class handle in JvmtiThreadState class.
// This redefined class is sent to agent event handler for class file
// load hook event.
! state->set_class_being_redefined(the_class, _class_load_kind);
! InstanceKlass* scratch_class = SystemDictionary::parse_stream(
! the_class_sym,
the_class_loader,
protection_domain,
&st,
THREAD);
// Clear class_being_redefined just to be sure.
state->clear_class_being_redefined();
// TODO: if this is retransform, and nothing changed we can skip it
// Need to clean up allocated InstanceKlass if there's an error so assign
// the result here. Caller deallocates all the scratch classes in case of
// an error.
! _scratch_classes[i] = scratch_class;
if (HAS_PENDING_EXCEPTION) {
Symbol* ex_name = PENDING_EXCEPTION->klass()->name();
log_info(redefine, class, load, exceptions)("parse_stream exception: '%s'", ex_name->as_C_string());
CLEAR_PENDING_EXCEPTION;
*** 1104,1114 ****
// Information about the_class and scratch_class is temporarily
// recorded into jvmtiThreadState. This data is used to redirect
// the_class to scratch_class in the JVM_* functions called by the
// verifier. Please, refer to jvmtiThreadState.hpp for the detailed
// description.
! RedefineVerifyMark rvm(&the_class, &scratch_class, state);
Verifier::verify(
scratch_class, Verifier::ThrowException, true, THREAD);
}
if (HAS_PENDING_EXCEPTION) {
--- 1103,1113 ----
// Information about the_class and scratch_class is temporarily
// recorded into jvmtiThreadState. This data is used to redirect
// the_class to scratch_class in the JVM_* functions called by the
// verifier. Please, refer to jvmtiThreadState.hpp for the detailed
// description.
! RedefineVerifyMark rvm(the_class, scratch_class, state);
Verifier::verify(
scratch_class, Verifier::ThrowException, true, THREAD);
}
if (HAS_PENDING_EXCEPTION) {
*** 1136,1146 ****
}
if (VerifyMergedCPBytecodes) {
// verify what we have done during constant pool merging
{
! RedefineVerifyMark rvm(&the_class, &scratch_class, state);
Verifier::verify(scratch_class, Verifier::ThrowException, true, THREAD);
}
if (HAS_PENDING_EXCEPTION) {
Symbol* ex_name = PENDING_EXCEPTION->klass()->name();
--- 1135,1145 ----
}
if (VerifyMergedCPBytecodes) {
// verify what we have done during constant pool merging
{
! RedefineVerifyMark rvm(the_class, scratch_class, state);
Verifier::verify(scratch_class, Verifier::ThrowException, true, THREAD);
}
if (HAS_PENDING_EXCEPTION) {
Symbol* ex_name = PENDING_EXCEPTION->klass()->name();
*** 1432,1442 ****
// Merge constant pools between the_class and scratch_class and
// potentially rewrite bytecodes in scratch_class to use the merged
// constant pool.
jvmtiError VM_RedefineClasses::merge_cp_and_rewrite(
! instanceKlassHandle the_class, instanceKlassHandle scratch_class,
TRAPS) {
// worst case merged constant pool length is old and new combined
int merge_cp_length = the_class->constants()->length()
+ scratch_class->constants()->length();
--- 1431,1441 ----
// Merge constant pools between the_class and scratch_class and
// potentially rewrite bytecodes in scratch_class to use the merged
// constant pool.
jvmtiError VM_RedefineClasses::merge_cp_and_rewrite(
! InstanceKlass* the_class, InstanceKlass* scratch_class,
TRAPS) {
// worst case merged constant pool length is old and new combined
int merge_cp_length = the_class->constants()->length()
+ scratch_class->constants()->length();
*** 1481,1491 ****
_operands_index_map_count = 0;
int operands_index_map_len = ConstantPool::operand_array_length(scratch_cp->operands());
_operands_index_map_p = new intArray(operands_index_map_len, operands_index_map_len, -1);
// reference to the cp holder is needed for copy_operands()
! merge_cp->set_pool_holder(scratch_class());
bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp,
&merge_cp_length, THREAD);
merge_cp->set_pool_holder(NULL);
if (!result) {
--- 1480,1490 ----
_operands_index_map_count = 0;
int operands_index_map_len = ConstantPool::operand_array_length(scratch_cp->operands());
_operands_index_map_p = new intArray(operands_index_map_len, operands_index_map_len, -1);
// reference to the cp holder is needed for copy_operands()
! merge_cp->set_pool_holder(scratch_class);
bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp,
&merge_cp_length, THREAD);
merge_cp->set_pool_holder(NULL);
if (!result) {
*** 1566,1576 ****
return JVMTI_ERROR_NONE;
} // end merge_cp_and_rewrite()
// Rewrite constant pool references in klass scratch_class.
! bool VM_RedefineClasses::rewrite_cp_refs(instanceKlassHandle scratch_class,
TRAPS) {
// rewrite constant pool references in the methods:
if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) {
// propagate failure back to caller
--- 1565,1575 ----
return JVMTI_ERROR_NONE;
} // end merge_cp_and_rewrite()
// Rewrite constant pool references in klass scratch_class.
! bool VM_RedefineClasses::rewrite_cp_refs(InstanceKlass* scratch_class,
TRAPS) {
// rewrite constant pool references in the methods:
if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) {
// propagate failure back to caller
*** 1653,1663 ****
return true;
} // end rewrite_cp_refs()
// Rewrite constant pool references in the methods.
bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
! instanceKlassHandle scratch_class, TRAPS) {
Array<Method*>* methods = scratch_class->methods();
if (methods == NULL || methods->length() == 0) {
// no methods so nothing to do
--- 1652,1662 ----
return true;
} // end rewrite_cp_refs()
// Rewrite constant pool references in the methods.
bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
! InstanceKlass* scratch_class, TRAPS) {
Array<Method*>* methods = scratch_class->methods();
if (methods == NULL || methods->length() == 0) {
// no methods so nothing to do
*** 1832,1842 ****
} // end rewrite_cp_refs_in_method()
// Rewrite constant pool references in the class_annotations field.
bool VM_RedefineClasses::rewrite_cp_refs_in_class_annotations(
! instanceKlassHandle scratch_class, TRAPS) {
AnnotationArray* class_annotations = scratch_class->class_annotations();
if (class_annotations == NULL || class_annotations->length() == 0) {
// no class_annotations so nothing to do
return true;
--- 1831,1841 ----
} // end rewrite_cp_refs_in_method()
// Rewrite constant pool references in the class_annotations field.
bool VM_RedefineClasses::rewrite_cp_refs_in_class_annotations(
! InstanceKlass* scratch_class, TRAPS) {
AnnotationArray* class_annotations = scratch_class->class_annotations();
if (class_annotations == NULL || class_annotations->length() == 0) {
// no class_annotations so nothing to do
return true;
*** 2122,2132 ****
} // end rewrite_cp_refs_in_element_value()
// Rewrite constant pool references in a fields_annotations field.
bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
! instanceKlassHandle scratch_class, TRAPS) {
Array<AnnotationArray*>* fields_annotations = scratch_class->fields_annotations();
if (fields_annotations == NULL || fields_annotations->length() == 0) {
// no fields_annotations so nothing to do
--- 2121,2131 ----
} // end rewrite_cp_refs_in_element_value()
// Rewrite constant pool references in a fields_annotations field.
bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
! InstanceKlass* scratch_class, TRAPS) {
Array<AnnotationArray*>* fields_annotations = scratch_class->fields_annotations();
if (fields_annotations == NULL || fields_annotations->length() == 0) {
// no fields_annotations so nothing to do
*** 2155,2165 ****
} // end rewrite_cp_refs_in_fields_annotations()
// Rewrite constant pool references in a methods_annotations field.
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
! instanceKlassHandle scratch_class, TRAPS) {
for (int i = 0; i < scratch_class->methods()->length(); i++) {
Method* m = scratch_class->methods()->at(i);
AnnotationArray* method_annotations = m->constMethod()->method_annotations();
--- 2154,2164 ----
} // end rewrite_cp_refs_in_fields_annotations()
// Rewrite constant pool references in a methods_annotations field.
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
! InstanceKlass* scratch_class, TRAPS) {
for (int i = 0; i < scratch_class->methods()->length(); i++) {
Method* m = scratch_class->methods()->at(i);
AnnotationArray* method_annotations = m->constMethod()->method_annotations();
*** 2193,2203 ****
// annotation annotations[num_annotations];
// } parameter_annotations[num_parameters];
// }
//
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations(
! instanceKlassHandle scratch_class, TRAPS) {
for (int i = 0; i < scratch_class->methods()->length(); i++) {
Method* m = scratch_class->methods()->at(i);
AnnotationArray* method_parameter_annotations = m->constMethod()->parameter_annotations();
if (method_parameter_annotations == NULL
--- 2192,2202 ----
// annotation annotations[num_annotations];
// } parameter_annotations[num_parameters];
// }
//
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations(
! InstanceKlass* scratch_class, TRAPS) {
for (int i = 0; i < scratch_class->methods()->length(); i++) {
Method* m = scratch_class->methods()->at(i);
AnnotationArray* method_parameter_annotations = m->constMethod()->parameter_annotations();
if (method_parameter_annotations == NULL
*** 2242,2252 ****
// methods_default_annotations_typeArray {
// element_value default_value;
// }
//
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_default_annotations(
! instanceKlassHandle scratch_class, TRAPS) {
for (int i = 0; i < scratch_class->methods()->length(); i++) {
Method* m = scratch_class->methods()->at(i);
AnnotationArray* method_default_annotations = m->constMethod()->default_annotations();
if (method_default_annotations == NULL
--- 2241,2251 ----
// methods_default_annotations_typeArray {
// element_value default_value;
// }
//
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_default_annotations(
! InstanceKlass* scratch_class, TRAPS) {
for (int i = 0; i < scratch_class->methods()->length(); i++) {
Method* m = scratch_class->methods()->at(i);
AnnotationArray* method_default_annotations = m->constMethod()->default_annotations();
if (method_default_annotations == NULL
*** 2269,2279 ****
} // end rewrite_cp_refs_in_methods_default_annotations()
// Rewrite constant pool references in a class_type_annotations field.
bool VM_RedefineClasses::rewrite_cp_refs_in_class_type_annotations(
! instanceKlassHandle scratch_class, TRAPS) {
AnnotationArray* class_type_annotations = scratch_class->class_type_annotations();
if (class_type_annotations == NULL || class_type_annotations->length() == 0) {
// no class_type_annotations so nothing to do
return true;
--- 2268,2278 ----
} // end rewrite_cp_refs_in_methods_default_annotations()
// Rewrite constant pool references in a class_type_annotations field.
bool VM_RedefineClasses::rewrite_cp_refs_in_class_type_annotations(
! InstanceKlass* scratch_class, TRAPS) {
AnnotationArray* class_type_annotations = scratch_class->class_type_annotations();
if (class_type_annotations == NULL || class_type_annotations->length() == 0) {
// no class_type_annotations so nothing to do
return true;
*** 2287,2297 ****
} // end rewrite_cp_refs_in_class_type_annotations()
// Rewrite constant pool references in a fields_type_annotations field.
bool VM_RedefineClasses::rewrite_cp_refs_in_fields_type_annotations(
! instanceKlassHandle scratch_class, TRAPS) {
Array<AnnotationArray*>* fields_type_annotations = scratch_class->fields_type_annotations();
if (fields_type_annotations == NULL || fields_type_annotations->length() == 0) {
// no fields_type_annotations so nothing to do
return true;
--- 2286,2296 ----
} // end rewrite_cp_refs_in_class_type_annotations()
// Rewrite constant pool references in a fields_type_annotations field.
bool VM_RedefineClasses::rewrite_cp_refs_in_fields_type_annotations(
! InstanceKlass* scratch_class, TRAPS) {
Array<AnnotationArray*>* fields_type_annotations = scratch_class->fields_type_annotations();
if (fields_type_annotations == NULL || fields_type_annotations->length() == 0) {
// no fields_type_annotations so nothing to do
return true;
*** 2319,2329 ****
} // end rewrite_cp_refs_in_fields_type_annotations()
// Rewrite constant pool references in a methods_type_annotations field.
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_type_annotations(
! instanceKlassHandle scratch_class, TRAPS) {
for (int i = 0; i < scratch_class->methods()->length(); i++) {
Method* m = scratch_class->methods()->at(i);
AnnotationArray* method_type_annotations = m->constMethod()->type_annotations();
--- 2318,2328 ----
} // end rewrite_cp_refs_in_fields_type_annotations()
// Rewrite constant pool references in a methods_type_annotations field.
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_type_annotations(
! InstanceKlass* scratch_class, TRAPS) {
for (int i = 0; i < scratch_class->methods()->length(); i++) {
Method* m = scratch_class->methods()->at(i);
AnnotationArray* method_type_annotations = m->constMethod()->type_annotations();
*** 3072,3082 ****
// scratch_cp. If shrink is true, then scratch_cp_length elements
// are copied from scratch_cp to a smaller constant pool and the
// smaller constant pool is associated with scratch_class.
void VM_RedefineClasses::set_new_constant_pool(
ClassLoaderData* loader_data,
! instanceKlassHandle scratch_class, constantPoolHandle scratch_cp,
int scratch_cp_length, TRAPS) {
assert(scratch_cp->length() >= scratch_cp_length, "sanity check");
// scratch_cp is a merged constant pool and has enough space for a
// worst case merge situation. We want to associate the minimum
--- 3071,3081 ----
// scratch_cp. If shrink is true, then scratch_cp_length elements
// are copied from scratch_cp to a smaller constant pool and the
// smaller constant pool is associated with scratch_class.
void VM_RedefineClasses::set_new_constant_pool(
ClassLoaderData* loader_data,
! InstanceKlass* scratch_class, constantPoolHandle scratch_cp,
int scratch_cp_length, TRAPS) {
assert(scratch_cp->length() >= scratch_cp_length, "sanity check");
// scratch_cp is a merged constant pool and has enough space for a
// worst case merge situation. We want to associate the minimum
*** 3089,3099 ****
assert(version != 0, "sanity check");
smaller_cp->set_version(version);
// attach klass to new constant pool
// reference to the cp holder is needed for copy_operands()
! smaller_cp->set_pool_holder(scratch_class());
scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD);
if (HAS_PENDING_EXCEPTION) {
// Exception is handled in the caller
loader_data->add_to_deallocate_list(smaller_cp());
--- 3088,3098 ----
assert(version != 0, "sanity check");
smaller_cp->set_version(version);
// attach klass to new constant pool
// reference to the cp holder is needed for copy_operands()
! smaller_cp->set_pool_holder(scratch_class);
scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD);
if (HAS_PENDING_EXCEPTION) {
// Exception is handled in the caller
loader_data->add_to_deallocate_list(smaller_cp());
*** 3266,3280 ****
void VM_RedefineClasses::AdjustCpoolCacheAndVtable::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_oop);
// 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_oop == SystemDictionary::Object_klass()) {
k->vtable()->adjust_method_entries(the_class, &trace_name_printed);
} else if (k->is_instance_klass()) {
HandleMark hm(_thread);
InstanceKlass *ik = InstanceKlass::cast(k);
--- 3265,3279 ----
void VM_RedefineClasses::AdjustCpoolCacheAndVtable::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);
} else if (k->is_instance_klass()) {
HandleMark hm(_thread);
InstanceKlass *ik = InstanceKlass::cast(k);
*** 3289,3300 ****
// class loader can delegate to the bootstrap class loader.
//
// 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 =
! InstanceKlass::cast(_the_class_oop)->class_loader() != NULL;
if (is_user_defined && ik->class_loader() == NULL) {
return;
}
// Fix the vtable embedded in the_class and subclasses of the_class,
--- 3288,3298 ----
// class loader can delegate to the bootstrap class loader.
//
// 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) {
return;
}
// Fix the vtable embedded in the_class and subclasses of the_class,
*** 3309,3321 ****
// 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_oop->is_interface()
! || _the_class_oop == SystemDictionary::internal_Unsafe_klass()
! || ik->is_subtype_of(_the_class_oop))) {
// 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);
--- 3307,3319 ----
// 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);
*** 3326,3338 ****
// 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_oop->is_interface()
! || _the_class_oop == SystemDictionary::internal_Unsafe_klass()
! || ik->is_subclass_of(_the_class_oop))) {
// ik->itable() creates a wrapper object; rm cleans it up
ResourceMark rm(_thread);
ik->itable()->adjust_method_entries(the_class, &trace_name_printed);
}
--- 3324,3336 ----
// 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))) {
// ik->itable() creates a wrapper object; rm cleans it up
ResourceMark rm(_thread);
ik->itable()->adjust_method_entries(the_class, &trace_name_printed);
}
*** 3351,3361 ****
// updated. We can simply start with the previous version(s) in
// that case.
constantPoolHandle other_cp;
ConstantPoolCache* cp_cache;
! if (ik != _the_class_oop) {
// 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);
--- 3349,3359 ----
// updated. We can simply start with the previous version(s) in
// that case.
constantPoolHandle other_cp;
ConstantPoolCache* cp_cache;
! if (ik != _the_class) {
// 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);
*** 3497,3507 ****
obsolete_count++;
// obsolete methods need a unique idnum so they become new entries in
// the jmethodID cache in InstanceKlass
assert(old_method->method_idnum() == new_method->method_idnum(), "must match");
! u2 num = InstanceKlass::cast(_the_class_oop)->next_method_idnum();
if (num != ConstMethod::UNSET_IDNUM) {
old_method->set_method_idnum(num);
}
// With tracing we try not to "yack" too much. The position of
--- 3495,3505 ----
obsolete_count++;
// obsolete methods need a unique idnum so they become new entries in
// the jmethodID cache in InstanceKlass
assert(old_method->method_idnum() == new_method->method_idnum(), "must match");
! u2 num = InstanceKlass::cast(_the_class)->next_method_idnum();
if (num != ConstMethod::UNSET_IDNUM) {
old_method->set_method_idnum(num);
}
// With tracing we try not to "yack" too much. The position of
*** 3561,3571 ****
// Simultaneous add and remove 1_m -> 2_m
// Same, caused by prefix removal only 3_2_1_m -> 3_2_m
//
class TransferNativeFunctionRegistration {
private:
! instanceKlassHandle the_class;
int prefix_count;
char** prefixes;
// Recursively search the binary tree of possibly prefixed method names.
// Iteration could be used if all agents were well behaved. Full tree walk is
--- 3559,3569 ----
// Simultaneous add and remove 1_m -> 2_m
// Same, caused by prefix removal only 3_2_1_m -> 3_2_m
//
class TransferNativeFunctionRegistration {
private:
! InstanceKlass* the_class;
int prefix_count;
char** prefixes;
// Recursively search the binary tree of possibly prefixed method names.
// Iteration could be used if all agents were well behaved. Full tree walk is
*** 3576,3586 ****
// where 'prefix' is the prefix at that 'depth' (first prefix, second prefix,...)
Method* search_prefix_name_space(int depth, char* name_str, size_t name_len,
Symbol* signature) {
TempNewSymbol name_symbol = SymbolTable::probe(name_str, (int)name_len);
if (name_symbol != NULL) {
! Method* method = the_class()->lookup_method(name_symbol, signature);
if (method != NULL) {
// Even if prefixed, intermediate methods must exist.
if (method->is_native()) {
// Wahoo, we found a (possibly prefixed) version of the method, return it.
return method;
--- 3574,3584 ----
// where 'prefix' is the prefix at that 'depth' (first prefix, second prefix,...)
Method* search_prefix_name_space(int depth, char* name_str, size_t name_len,
Symbol* signature) {
TempNewSymbol name_symbol = SymbolTable::probe(name_str, (int)name_len);
if (name_symbol != NULL) {
! Method* method = the_class->lookup_method(name_symbol, signature);
if (method != NULL) {
// Even if prefixed, intermediate methods must exist.
if (method->is_native()) {
// Wahoo, we found a (possibly prefixed) version of the method, return it.
return method;
*** 3639,3649 ****
}
public:
// Construct a native method transfer processor for this class.
! TransferNativeFunctionRegistration(instanceKlassHandle _the_class) {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
the_class = _the_class;
prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count);
}
--- 3637,3647 ----
}
public:
// Construct a native method transfer processor for this class.
! TransferNativeFunctionRegistration(InstanceKlass* _the_class) {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
the_class = _the_class;
prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count);
}
*** 3666,3676 ****
}
}
};
// Don't lose the association between a native method and its JNI function.
! void VM_RedefineClasses::transfer_old_native_function_registrations(instanceKlassHandle the_class) {
TransferNativeFunctionRegistration transfer(the_class);
transfer.transfer_registrations(_deleted_methods, _deleted_methods_length);
transfer.transfer_registrations(_matching_old_methods, _matching_methods_length);
}
--- 3664,3674 ----
}
}
};
// Don't lose the association between a native method and its JNI function.
! void VM_RedefineClasses::transfer_old_native_function_registrations(InstanceKlass* the_class) {
TransferNativeFunctionRegistration transfer(the_class);
transfer.transfer_registrations(_deleted_methods, _deleted_methods_length);
transfer.transfer_registrations(_matching_old_methods, _matching_methods_length);
}
*** 3687,3703 ****
// thrown away. As can_redefine_classes has been obtained then
// all future compilations will record dependencies so second and
// subsequent calls to RedefineClasses need only throw away code
// that depends on the class.
//
! void VM_RedefineClasses::flush_dependent_code(instanceKlassHandle k_h, TRAPS) {
assert_locked_or_safepoint(Compile_lock);
// All dependencies have been recorded from startup or this is a second or
// subsequent use of RedefineClasses
if (JvmtiExport::all_dependencies_are_recorded()) {
! CodeCache::flush_evol_dependents_on(k_h);
} else {
CodeCache::mark_all_nmethods_for_deoptimization();
ResourceMark rm(THREAD);
DeoptimizationMarker dm;
--- 3685,3701 ----
// thrown away. As can_redefine_classes has been obtained then
// all future compilations will record dependencies so second and
// subsequent calls to RedefineClasses need only throw away code
// that depends on the class.
//
! void VM_RedefineClasses::flush_dependent_code(InstanceKlass* ik, TRAPS) {
assert_locked_or_safepoint(Compile_lock);
// All dependencies have been recorded from startup or this is a second or
// subsequent use of RedefineClasses
if (JvmtiExport::all_dependencies_are_recorded()) {
! CodeCache::flush_evol_dependents_on(ik);
} else {
CodeCache::mark_all_nmethods_for_deoptimization();
ResourceMark rm(THREAD);
DeoptimizationMarker dm;
*** 3773,3784 ****
assert(_matching_methods_length + _deleted_methods_length == _old_methods->length(), "sanity");
assert(_matching_methods_length + _added_methods_length == _new_methods->length(), "sanity");
}
! void VM_RedefineClasses::swap_annotations(instanceKlassHandle the_class,
! instanceKlassHandle scratch_class) {
// Swap annotation fields values
Annotations* old_annotations = the_class->annotations();
the_class->set_annotations(scratch_class->annotations());
scratch_class->set_annotations(old_annotations);
}
--- 3771,3782 ----
assert(_matching_methods_length + _deleted_methods_length == _old_methods->length(), "sanity");
assert(_matching_methods_length + _added_methods_length == _new_methods->length(), "sanity");
}
! void VM_RedefineClasses::swap_annotations(InstanceKlass* the_class,
! InstanceKlass* scratch_class) {
// Swap annotation fields values
Annotations* old_annotations = the_class->annotations();
the_class->set_annotations(scratch_class->annotations());
scratch_class->set_annotations(old_annotations);
}
*** 3795,3831 ****
// ClassLoaderDataGraph::classes_do() facility which only allows
// a helper method to be specified. The interesting parameters
// that we would like to pass to the helper method are saved in
// static global fields in the VM operation.
void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
! Klass* scratch_class_oop, TRAPS) {
HandleMark hm(THREAD); // make sure handles from this call are freed
if (log_is_enabled(Info, redefine, class, timer)) {
_timer_rsc_phase1.start();
}
! 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());
// 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();
compute_added_deleted_matching_methods();
update_jmethod_ids();
// Attach new constant pool to the original klass. The original
// klass still refers to the old constant pool (for now).
! scratch_class->constants()->set_pool_holder(the_class());
#if 0
// In theory, with constant pool merging in place we should be able
// to save space by using the new, merged constant pool in place of
// the old constant pool(s). By "pool(s)" I mean the constant pool in
--- 3793,3828 ----
// ClassLoaderDataGraph::classes_do() facility which only allows
// a helper method to be specified. The interesting parameters
// that we would like to pass to the helper method are saved in
// static global fields in the VM operation.
void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
! InstanceKlass* scratch_class, TRAPS) {
HandleMark hm(THREAD); // make sure handles from this call are freed
if (log_is_enabled(Info, redefine, class, timer)) {
_timer_rsc_phase1.start();
}
! InstanceKlass* the_class = 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);
// 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 = the_class;
compute_added_deleted_matching_methods();
update_jmethod_ids();
// Attach new constant pool to the original klass. The original
// klass still refers to the old constant pool (for now).
! scratch_class->constants()->set_pool_holder(the_class);
#if 0
// In theory, with constant pool merging in place we should be able
// to save space by using the new, merged constant pool in place of
// the old constant pool(s). By "pool(s)" I mean the constant pool in
*** 3851,3867 ****
// original constant pool. In order for the new methods to work when they
// become old methods, they need to keep their updated copy of the constant pool.
{
// walk all previous versions of the klass
! InstanceKlass *ik = (InstanceKlass *)the_class();
PreviousVersionWalker pvw(ik);
! instanceKlassHandle ikh;
do {
! ikh = pvw.next_previous_version();
! if (!ikh.is_null()) {
! ik = ikh();
// attach previous version of klass to the new constant pool
ik->set_constants(scratch_class->constants());
// Attach each method in the previous version of klass to the
--- 3848,3863 ----
// original constant pool. In order for the new methods to work when they
// become old methods, they need to keep their updated copy of the constant pool.
{
// walk all previous versions of the klass
! InstanceKlass *ik = (InstanceKlass *)the_class;
PreviousVersionWalker pvw(ik);
! InstanceKlass* ik;
do {
! ik = pvw.next_previous_version();
! if (ik != NULL) {
// attach previous version of klass to the new constant pool
ik->set_constants(scratch_class->constants());
// Attach each method in the previous version of klass to the
*** 3870,3880 ****
for (int i = prev_methods->length() - 1; i >= 0; i--) {
Method* method = prev_methods->at(i);
method->set_constants(scratch_class->constants());
}
}
! } while (!ikh.is_null());
}
#endif
// Replace methods and constantpool
the_class->set_methods(_new_methods);
--- 3866,3876 ----
for (int i = prev_methods->length() - 1; i >= 0; i--) {
Method* method = prev_methods->at(i);
method->set_constants(scratch_class->constants());
}
}
! } while (ik != NULL);
}
#endif
// Replace methods and constantpool
the_class->set_methods(_new_methods);
*** 4039,4062 ****
// JSR-292 support
MemberNameTable* mnt = the_class->member_names();
if (mnt != NULL) {
bool trace_name_printed = false;
! mnt->adjust_method_entries(the_class(), &trace_name_printed);
}
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.
the_class->oop_map_cache()->flush_obsolete_entries();
}
{
ResourceMark rm(THREAD);
// increment the classRedefinedCount field in the_class and in any
// direct and indirect subclasses of the_class
- 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->java_mirror()), os::available_memory() >> 10);
Events::log_redefinition(THREAD, "redefined class name=%s, count=%d",
the_class->external_name(),
--- 4035,4058 ----
// JSR-292 support
MemberNameTable* mnt = the_class->member_names();
if (mnt != NULL) {
bool trace_name_printed = false;
! mnt->adjust_method_entries(the_class, &trace_name_printed);
}
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.
the_class->oop_map_cache()->flush_obsolete_entries();
}
+ increment_class_counter((InstanceKlass *)the_class, THREAD);
{
ResourceMark rm(THREAD);
// increment the classRedefinedCount field in the_class and in any
// direct and indirect subclasses of the_class
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->java_mirror()), os::available_memory() >> 10);
Events::log_redefinition(THREAD, "redefined class name=%s, count=%d",
the_class->external_name(),
*** 4073,4084 ****
oop class_mirror = ik->java_mirror();
Klass* class_oop = java_lang_Class::as_Klass(class_mirror);
int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1;
java_lang_Class::set_classRedefinedCount(class_mirror, new_count);
! if (class_oop != _the_class_oop) {
! // _the_class_oop count is printed at end of redefine_single_class()
log_debug(redefine, class, subclass)("updated count in subclass=%s to %d", ik->external_name(), new_count);
}
for (Klass *subk = ik->subklass(); subk != NULL;
subk = subk->next_sibling()) {
--- 4069,4080 ----
oop class_mirror = ik->java_mirror();
Klass* class_oop = java_lang_Class::as_Klass(class_mirror);
int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1;
java_lang_Class::set_classRedefinedCount(class_mirror, new_count);
! if (class_oop != _the_class) {
! // _the_class count is printed at end of redefine_single_class()
log_debug(redefine, class, subclass)("updated count in subclass=%s to %d", ik->external_name(), new_count);
}
for (Klass *subk = ik->subklass(); subk != NULL;
subk = subk->next_sibling()) {
*** 4210,4219 ****
}
}
void VM_RedefineClasses::print_on_error(outputStream* st) const {
VM_Operation::print_on_error(st);
! if (_the_class_oop != NULL) {
ResourceMark rm;
! st->print_cr(", redefining class %s", _the_class_oop->external_name());
}
}
--- 4206,4215 ----
}
}
void VM_RedefineClasses::print_on_error(outputStream* st) const {
VM_Operation::print_on_error(st);
! if (_the_class != NULL) {
ResourceMark rm;
! st->print_cr(", redefining class %s", _the_class->external_name());
}
}
< prev index next >