< 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 >