inline int ClassVerifier::change_sig_to_verificationType( SignatureStream* sig_type, VerificationType* inference_type, TRAPS) { BasicType bt = sig_type->type(); switch (bt) { case T_OBJECT: case T_ARRAY: { symbolOop name = sig_type->as_symbol(CHECK_0); *inference_type = VerificationType::reference_type(symbolHandle(THREAD, name)); return 1; } case T_LONG: *inference_type = VerificationType::long_type(); *++inference_type = VerificationType::long2_type(); return 2; case T_DOUBLE: *inference_type = VerificationType::double_type(); *++inference_type = VerificationType::double2_type(); return 2; case T_INT: case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: *inference_type = VerificationType::integer_type(); return 1; case T_FLOAT: *inference_type = VerificationType::float_type(); return 1; default: ShouldNotReachHere(); return 1; } }
VerificationType StackMapFrame::set_locals_from_arg( const methodHandle m, VerificationType thisKlass, TRAPS) { symbolHandle signature(THREAD, m->signature()); SignatureStream ss(signature); int init_local_num = 0; if (!m->is_static()) { init_local_num++; // add one extra argument for instance method if (m->name() == vmSymbols::object_initializer_name() && thisKlass.name() != vmSymbols::java_lang_Object()) { _locals[0] = VerificationType::uninitialized_this_type(); _flags |= FLAG_THIS_UNINIT; } else { _locals[0] = thisKlass; } } // local num may be greater than size of parameters because long/double occupies two slots while(!ss.at_return_type()) { init_local_num += _verifier->change_sig_to_verificationType( &ss, &_locals[init_local_num], CHECK_VERIFY_(verifier(), VerificationType::bogus_type())); ss.next(); } _locals_size = init_local_num; switch (ss.type()) { case T_OBJECT: case T_ARRAY: { symbolOop sig = ss.as_symbol(CHECK_(VerificationType::bogus_type())); return VerificationType::reference_type(symbolHandle(THREAD, sig)); } case T_INT: return VerificationType::integer_type(); case T_BYTE: return VerificationType::byte_type(); case T_CHAR: return VerificationType::char_type(); case T_SHORT: return VerificationType::short_type(); case T_BOOLEAN: return VerificationType::boolean_type(); case T_FLOAT: return VerificationType::float_type(); case T_DOUBLE: return VerificationType::double_type(); case T_LONG: return VerificationType::long_type(); case T_VOID: return VerificationType::bogus_type(); default: ShouldNotReachHere(); } return VerificationType::bogus_type(); }
VerificationType cp_index_to_type(int index, constantPoolHandle cp, TRAPS) { return VerificationType::reference_type( symbolHandle(THREAD, cp->klass_name_at(index))); }
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; }