jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { // For consistency allocate memory using os::malloc wrapper. _k_h_new = (instanceKlassHandle *) os::malloc(sizeof(instanceKlassHandle) * _class_count); ResourceMark rm(THREAD); JvmtiThreadState *state = JavaThread::current()->jvmti_thread_state(); assert(state != NULL, "JvmtiThreadState not initialized"); for (int i = 0; i < _class_count; i++) { oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass); klassOop k_oop = java_lang_Class::as_klassOop(mirror); instanceKlassHandle k_h = instanceKlassHandle(THREAD, k_oop); symbolHandle k_name = symbolHandle(THREAD, k_h->name()); ClassFileStream st((u1*) _class_defs[i].class_bytes, _class_defs[i].class_byte_count, (char *)"__VM_RedefineClasses__"); // Parse the stream. Handle k_loader_h(THREAD, k_h->class_loader()); Handle 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(&k_h); klassOop k = SystemDictionary::parse_stream(k_name, k_loader_h, protection_domain, &st, THREAD); // Clear class_being_redefined just to be sure. state->set_class_being_redefined(NULL); instanceKlassHandle k_h_new (THREAD, k); if (HAS_PENDING_EXCEPTION) { symbolOop ex_name = PENDING_EXCEPTION->klass()->klass_part()->name(); CLEAR_PENDING_EXCEPTION; if (ex_name == vmSymbols::java_lang_UnsupportedClassVersionError()) { return JVMTI_ERROR_UNSUPPORTED_VERSION; } else if (ex_name == vmSymbols::java_lang_ClassFormatError()) { return JVMTI_ERROR_INVALID_CLASS_FORMAT; } else if (ex_name == vmSymbols::java_lang_ClassCircularityError()) { return JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION; } else if (ex_name == vmSymbols::java_lang_NoClassDefFoundError()) { // The message will be "XXX (wrong name: YYY)" return JVMTI_ERROR_NAMES_DONT_MATCH; } else { // Just in case more exceptions can be thrown.. return JVMTI_ERROR_FAILS_VERIFICATION; } } // All its super classes should be linked to // initialize the vtable. instanceKlassHandle super(THREAD, k_h_new->super()); if (super.not_null() && !super->is_linked()) { super->link_class(THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return JVMTI_ERROR_INTERNAL; } } // See instanceKlass::link_klass_impl() { ObjectLocker ol(k_h_new, THREAD); Verifier::verify_byte_codes(k_h_new, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return JVMTI_ERROR_FAILS_VERIFICATION; } Rewriter::rewrite(k_h_new, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return JVMTI_ERROR_INTERNAL; } } jvmtiError res = compare_class_versions(k_h, k_h_new); if (res != JVMTI_ERROR_NONE) return res; _k_h_new[i] = k_h_new; } return JVMTI_ERROR_NONE; }
jvmdiError load_new_class_versions(TRAPS) { // For consistency allocate memory using os::malloc wrapper. _k_h_new = (instanceKlassHandle *) os::malloc(sizeof(instanceKlassHandle) * _class_count); ResourceMark rm(THREAD); for (int i = 0; i < _class_count; i++) { oop mirror = JNIHandles::resolve_non_null(_class_defs[i].clazz); klassOop k_oop = java_lang_Class::as_klassOop(mirror); instanceKlassHandle k_h = instanceKlassHandle(THREAD, k_oop); symbolHandle k_name = symbolHandle(THREAD, k_h->name()); ClassFileStream st((u1*) _class_defs[i].class_bytes, _class_defs[i].class_byte_count, NULL); // Parse the stream. Handle k_loader_h(THREAD, k_h->class_loader()); Handle protection_domain; klassOop k = SystemDictionary::parse_stream(k_name, k_loader_h, protection_domain, &st, THREAD); instanceKlassHandle k_h_new (THREAD, k); if (HAS_PENDING_EXCEPTION) { if (PENDING_EXCEPTION->klass()->klass_part()->name() == vmSymbols::java_lang_UnsupportedClassVersionError()) { CLEAR_PENDING_EXCEPTION; return JVMDI_ERROR_UNSUPPORTED_VERSION; } else if (PENDING_EXCEPTION->klass()->klass_part()->name() == vmSymbols::java_lang_ClassFormatError()) { CLEAR_PENDING_EXCEPTION; return JVMDI_ERROR_INVALID_CLASS_FORMAT; } else if (PENDING_EXCEPTION->klass()->klass_part()->name() == vmSymbols::java_lang_ClassCircularityError()) { CLEAR_PENDING_EXCEPTION; return JVMDI_ERROR_CIRCULAR_CLASS_DEFINITION; } else if (PENDING_EXCEPTION->klass()->klass_part()->name() == vmSymbols::java_lang_NoClassDefFoundError()) { // The message will be "XXX (wrong name: YYY)" CLEAR_PENDING_EXCEPTION; return JVMDI_ERROR_NAMES_DONT_MATCH; } else { // Just in case more exceptions can be thrown.. return JVMDI_ERROR_FAILS_VERIFICATION; } } // See instanceKlass::link_klass_impl() { ObjectLocker ol(k_h_new, THREAD); Verifier::verify_byte_codes(k_h_new, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return JVMDI_ERROR_FAILS_VERIFICATION; } Rewriter::rewrite(k_h_new, THREAD); // No exception can happen here } jvmdiError res = compare_class_versions(k_h, k_h_new); if (res != JVMDI_ERROR_NONE) return res; _k_h_new[i] = k_h_new; } return JVMDI_ERROR_NONE; }