src/share/vm/classfile/classFileParser.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** old/src/share/vm/classfile/classFileParser.cpp	Tue Nov 11 16:54:04 2008
--- new/src/share/vm/classfile/classFileParser.cpp	Tue Nov 11 16:54:04 2008

*** 166,180 **** --- 166,192 ---- u1* utf8_buffer = cfs->get_u1_buffer(); assert(utf8_buffer != NULL, "null utf8 buffer"); // Got utf8 string, guarantee utf8_length+1 bytes, set stream position forward. cfs->guarantee_more(utf8_length+1, CHECK); // utf8 string, tag/access_flags cfs->skip_u1_fast(utf8_length); + // Before storing the symbol, make sure it's legal if (_need_verify) { verify_legal_utf8((unsigned char*)utf8_buffer, utf8_length, CHECK); } + if (AnonymousClasses && has_cp_patch_at(index)) { + Handle patch = clear_cp_patch_at(index); + guarantee_property(java_lang_String::is_instance(patch()), + "Illegal utf8 patch at %d in class file %s", + index, CHECK); + char* str = java_lang_String::as_utf8_string(patch()); + // (could use java_lang_String::as_symbol instead, but might as well batch them) + utf8_buffer = (u1*) str; + utf8_length = (int) strlen(str); + } + unsigned int hash; symbolOop result = SymbolTable::lookup_only((char*)utf8_buffer, utf8_length, hash); if (result == NULL) { names[names_count] = (char*)utf8_buffer; lengths[names_count] = utf8_length;
*** 243,253 **** --- 255,265 ---- case JVM_CONSTANT_InterfaceMethodref : { if (!_need_verify) break; int klass_ref_index = cp->klass_ref_index_at(index); int name_and_type_ref_index = cp->name_and_type_ref_index_at(index); check_property(valid_cp_range(klass_ref_index, length) && ! cp->tag_at(klass_ref_index).is_klass_reference(), ! is_klass_reference(cp, klass_ref_index), "Invalid constant pool index %u in class file %s", klass_ref_index, CHECK_(nullHandle)); check_property(valid_cp_range(name_and_type_ref_index, length) && cp->tag_at(name_and_type_ref_index).is_name_and_type(),
*** 324,343 **** --- 336,385 ---- ShouldNotReachHere(); break; } // end of switch } // end of for + if (_cp_patches != NULL) { + // need to treat this_class specially... + assert(AnonymousClasses, ""); + int this_class_index; + { + cfs->guarantee_more(8, CHECK_(nullHandle)); // flags, this_class, super_class, infs_len + u1* mark = cfs->current(); + u2 flags = cfs->get_u2_fast(); + this_class_index = cfs->get_u2_fast(); + cfs->set_current(mark); // revert to mark + } + + for (index = 1; index < length; index++) { // Index 0 is unused + if (has_cp_patch_at(index)) { + guarantee_property(index != this_class_index, + "Illegal constant pool patch to self at %d in class file %s", + index, CHECK_(nullHandle)); + patch_constant_pool(cp, index, cp_patch_at(index), CHECK_(nullHandle)); + } + } + // Ensure that all the patches have been used. + for (index = 0; index < _cp_patches->length(); index++) { + guarantee_property(!has_cp_patch_at(index), + "Unused constant pool patch at %d in class file %s", + index, CHECK_(nullHandle)); + } + } + if (!_need_verify) { return cp; } // second verification pass - checks the strings are of the right format. + // but not yet to the other entries for (index = 1; index < length; index++) { jbyte tag = cp->tag_at(index).value(); switch (tag) { case JVM_CONSTANT_UnresolvedClass: { symbolHandle class_name(THREAD, cp->unresolved_klass_at(index)); + // check the name, even if _cp_patches will overwrite it verify_legal_class_name(class_name, CHECK_(nullHandle)); break; } case JVM_CONSTANT_Fieldref: case JVM_CONSTANT_Methodref:
*** 376,385 **** --- 418,494 ---- return cp; } + void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS) { + assert(AnonymousClasses, ""); + BasicType patch_type = T_VOID; + switch (cp->tag_at(index).value()) { + + case JVM_CONSTANT_UnresolvedClass : + // Patching a class means pre-resolving it. + // The name in the constant pool is ignored. + if (patch->klass() == SystemDictionary::class_klass()) { // %%% java_lang_Class::is_instance + guarantee_property(!java_lang_Class::is_primitive(patch()), + "Illegal class patch at %d in class file %s", + index, CHECK); + cp->klass_at_put(index, java_lang_Class::as_klassOop(patch())); + } else { + guarantee_property(java_lang_String::is_instance(patch()), + "Illegal class patch at %d in class file %s", + index, CHECK); + symbolHandle name = java_lang_String::as_symbol(patch(), CHECK); + cp->unresolved_klass_at_put(index, name()); + } + break; + + case JVM_CONSTANT_UnresolvedString : + // Patching a string means pre-resolving it. + // The spelling in the constant pool is ignored. + // The constant reference may be any object whatever. + // If it is not a real interned string, the constant is referred + // to as a "pseudo-string", and must be presented to the CP + // explicitly, because it may require scavenging. + cp->pseudo_string_at_put(index, patch()); + break; + + case JVM_CONSTANT_Integer : patch_type = T_INT; goto patch_prim; + case JVM_CONSTANT_Float : patch_type = T_FLOAT; goto patch_prim; + case JVM_CONSTANT_Long : patch_type = T_LONG; goto patch_prim; + case JVM_CONSTANT_Double : patch_type = T_DOUBLE; goto patch_prim; + patch_prim: + { + jvalue value; + BasicType value_type = java_lang_boxing_object::get_value(patch(), &value); + guarantee_property(value_type == patch_type, + "Illegal primitive patch at %d in class file %s", + index, CHECK); + switch (value_type) { + case T_INT: cp->int_at_put(index, value.i); break; + case T_FLOAT: cp->float_at_put(index, value.f); break; + case T_LONG: cp->long_at_put(index, value.j); break; + case T_DOUBLE: cp->double_at_put(index, value.d); break; + default: assert(false, ""); + } + } + break; + + default: + // %%% TODO: put method handles into CONSTANT_InterfaceMethodref, etc. + guarantee_property(!has_cp_patch_at(index), + "Illegal unexpected patch at %d in class file %s", + index, CHECK); + return; + } + + // On fall-through, mark the patch as used. + clear_cp_patch_at(index); + } + + + class NameSigHash: public ResourceObj { public: symbolOop _name; // name symbolOop _sig; // signature NameSigHash* _next; // Next entry in hash table
*** 446,460 **** --- 555,573 ---- objArrayHandle interfaces (THREAD, interface_oop); int index; for (index = 0; index < length; index++) { u2 interface_index = cfs->get_u2(CHECK_(nullHandle)); + KlassHandle interf; check_property( valid_cp_range(interface_index, cp->length()) && ! cp->tag_at(interface_index).is_unresolved_klass(), ! is_klass_reference(cp, interface_index), "Interface name has bad constant pool index %u in class file %s", interface_index, CHECK_(nullHandle)); + if (cp->tag_at(interface_index).is_klass()) { + interf = KlassHandle(THREAD, cp->resolved_klass_at(interface_index)); + } else { symbolHandle unresolved_klass (THREAD, cp->klass_name_at(interface_index)); // Don't need to check legal name because it's checked when parsing constant pool. // But need to make sure it's not an array type. guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY,
*** 463,475 **** --- 576,591 ---- vmtimer->suspend(); // do not count recursive loading twice // Call resolve_super so classcircularity is checked klassOop k = SystemDictionary::resolve_super_or_fail(class_name, unresolved_klass, class_loader, protection_domain, false, CHECK_(nullHandle)); ! KlassHandle interf (THREAD, k); ! interf = KlassHandle(THREAD, k); vmtimer->resume(); + cp->klass_at_put(interface_index, interf()); // eagerly resolve + } + if (!Klass::cast(interf())->is_interface()) { THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", nullHandle); } interfaces->obj_at_put(index, interf()); }
*** 875,886 **** --- 991,1001 ---- "Illegal exception table range in class file %s", CHECK_(nullHandle)); guarantee_property(handler_pc < code_length, "Illegal exception table handler in class file %s", CHECK_(nullHandle)); if (catch_type_index != 0) { guarantee_property(valid_cp_range(catch_type_index, cp->length()) && (cp->tag_at(catch_type_index).is_klass() || cp->tag_at(catch_type_index).is_unresolved_klass()), + is_klass_reference(cp, catch_type_index), "Catch type in exception table has bad constant type in class file %s", CHECK_(nullHandle)); } } exception_handlers->int_at_put(index++, start_pc); exception_handlers->int_at_put(index++, end_pc);
*** 1115,1125 **** --- 1230,1240 ---- if (tag == ITEM_Long || tag == ITEM_Double) { index++; } else if (tag == ITEM_Object) { u2 class_index = u2_array[i2++] = cfs->get_u2(CHECK); guarantee_property(valid_cp_range(class_index, cp->length()) && ! cp->tag_at(class_index).is_unresolved_klass(), ! is_klass_reference(cp, class_index), "Bad class index %u in StackMap in class file %s", class_index, CHECK); } else if (tag == ITEM_Uninitialized) { u2 offset = u2_array[i2++] = cfs->get_u2(CHECK); guarantee_property(
*** 1181,1191 **** --- 1296,1306 ---- cfs->guarantee_more(2 * len, CHECK_NULL); for (int i = 0; i < len; i++) { checked_exception = cfs->get_u2_fast(); check_property( valid_cp_range(checked_exception, cp->length()) && ! cp->tag_at(checked_exception).is_klass_reference(), ! is_klass_reference(cp, checked_exception), "Exception name has bad type at constant pool %u in class file %s", checked_exception, CHECK_NULL); } } // check exceptions attribute length
*** 1916,1934 **** --- 2031,2049 ---- // Inner class index u2 inner_class_info_index = cfs->get_u2_fast(); check_property( inner_class_info_index == 0 || (valid_cp_range(inner_class_info_index, cp_size) && ! cp->tag_at(inner_class_info_index).is_klass_reference()), ! is_klass_reference(cp, inner_class_info_index)), "inner_class_info_index %u has bad constant type in class file %s", inner_class_info_index, CHECK_0); // Outer class index u2 outer_class_info_index = cfs->get_u2_fast(); check_property( outer_class_info_index == 0 || (valid_cp_range(outer_class_info_index, cp_size) && ! cp->tag_at(outer_class_info_index).is_klass_reference()), ! is_klass_reference(cp, outer_class_info_index)), "outer_class_info_index %u has bad constant type in class file %s", outer_class_info_index, CHECK_0); // Inner class name u2 inner_name_index = cfs->get_u2_fast(); check_property(
*** 2086,2096 **** --- 2201,2211 ---- if (class_index == 0) { classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", CHECK); } // Validate the constant pool indices and types if (!cp->is_within_bounds(class_index) || ! !cp->tag_at(class_index).is_klass_reference()) { ! !is_klass_reference(cp, class_index)) { classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK); } if (method_index != 0 && (!cp->is_within_bounds(method_index) || !cp->tag_at(method_index).is_name_and_type())) {
*** 2347,2356 **** --- 2462,2472 ---- instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, Handle class_loader, Handle protection_domain, + GrowableArray<Handle>* cp_patches, symbolHandle& parsed_name, TRAPS) { // So that JVMTI can cache class file in the state before retransformable agents // have modified it unsigned char *cached_class_file_bytes = NULL;
*** 2378,2387 **** --- 2494,2504 ---- cfs = new ClassFileStream(ptr, end_ptr - ptr, cfs->source()); set_stream(cfs); } } + _cp_patches = cp_patches; instanceKlassHandle nullHandle; // Figure out whether we can skip format checking (matching classic VM behavior) _need_verify = Verifier::should_verify_for(class_loader());
*** 2508,2525 **** --- 2625,2650 ---- "Invalid superclass index %u in class file %s", super_class_index, CHECK_(nullHandle)); } else { check_property(valid_cp_range(super_class_index, cp_size) && ! cp->tag_at(super_class_index).is_unresolved_klass(), ! is_klass_reference(cp, super_class_index), "Invalid superclass index %u in class file %s", super_class_index, CHECK_(nullHandle)); // The class name should be legal because it is checked when parsing constant pool. // However, make sure it is not an array type. + bool is_array = false; + if (cp->tag_at(super_class_index).is_klass()) { + super_klass = instanceKlassHandle(THREAD, cp->resolved_klass_at(super_class_index)); + if (_need_verify) + is_array = super_klass->oop_is_array(); + } else if (_need_verify) { + is_array = (cp->unresolved_klass_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY); + } if (_need_verify) { ! guarantee_property(cp->unresolved_klass_at(super_class_index)->byte_at(0) != JVM_SIGNATURE_ARRAY, ! guarantee_property(!is_array, "Bad superclass name in class file %s", CHECK_(nullHandle)); } } // Interfaces
*** 2555,2565 **** --- 2680,2690 ---- objArrayHandle methods_annotations(THREAD, methods_annotations_oop); objArrayHandle methods_parameter_annotations(THREAD, methods_parameter_annotations_oop); objArrayHandle methods_default_annotations(THREAD, methods_default_annotations_oop); // We check super class after class file is parsed and format is checked ! if (super_class_index > 0 && super_klass.is_null()) { symbolHandle sk (THREAD, cp->klass_name_at(super_class_index)); if (access_flags.is_interface()) { // Before attempting to resolve the superclass, check for class format // errors not checked yet. guarantee_property(sk() == vmSymbols::java_lang_Object(),
*** 2572,2581 **** --- 2697,2709 ---- protection_domain, true, CHECK_(nullHandle)); KlassHandle kh (THREAD, k); super_klass = instanceKlassHandle(THREAD, kh()); + cp->klass_at_put(super_class_index, super_klass()); // eagerly resolve + } + if (super_klass.not_null()) { if (super_klass->is_interface()) { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbolHandles::java_lang_IncompatibleClassChangeError(),
*** 2998,3007 **** --- 3126,3136 ---- this_klass->set_has_final_method(); } this_klass->set_method_ordering(method_ordering()); this_klass->set_initial_method_idnum(methods->length()); this_klass->set_name(cp->klass_name_at(this_class_index)); + cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve this_klass->set_protection_domain(protection_domain()); this_klass->set_fields_annotations(fields_annotations()); this_klass->set_methods_annotations(methods_annotations()); this_klass->set_methods_parameter_annotations(methods_parameter_annotations()); this_klass->set_methods_default_annotations(methods_default_annotations());

src/share/vm/classfile/classFileParser.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File