< prev index next >

src/share/vm/classfile/classFileParser.cpp

Print this page

*** 389,398 **** --- 389,399 ---- // a bad CP entry has been detected previously so stop parsing and just return. return; } int index = 1; // declared outside of loops for portability + int num_klasses = 0; // first verification pass - validate cross references // and fixup class and string constants for (index = 1; index < length; index++) { // Index 0 is unused const jbyte tag = cp->tag_at(index).value();
*** 457,467 **** case JVM_CONSTANT_ClassIndex: { const int class_index = cp->klass_index_at(index); check_property(valid_symbol_at(class_index), "Invalid constant pool index %u in class file %s", class_index, CHECK); ! cp->unresolved_klass_at_put(index, cp->symbol_at(class_index)); break; } case JVM_CONSTANT_StringIndex: { const int string_index = cp->string_index_at(index); check_property(valid_symbol_at(string_index), --- 458,468 ---- case JVM_CONSTANT_ClassIndex: { const int class_index = cp->klass_index_at(index); check_property(valid_symbol_at(class_index), "Invalid constant pool index %u in class file %s", class_index, CHECK); ! cp->unresolved_klass_at_put(index, class_index, num_klasses++); break; } case JVM_CONSTANT_StringIndex: { const int string_index = cp->string_index_at(index); check_property(valid_symbol_at(string_index),
*** 548,559 **** --- 549,571 ---- break; } } // switch(tag) } // end of for + _first_patched_klass_resolved_index = num_klasses; + cp->allocate_resolved_klasses(_loader_data, num_klasses + _max_num_patched_klasses, CHECK); + if (_cp_patches != NULL) { // need to treat this_class specially... + + // Add dummy utf8 entries in the space reserved for names of patched classes. We'll use "*" + // for now. These will be replaced with actual names of the patched classes in patch_class(). + Symbol* s = vmSymbols::star_name(); + for (int n=_orig_cp_size; n<cp->length(); n++) { + cp->symbol_at_put(n, s); + } + int this_class_index; { stream->guarantee_more(8, CHECK); // flags, this_class, super_class, infs_len const u1* const mark = stream->current(); stream->skip_u2_fast(1); // skip flags
*** 699,708 **** --- 711,728 ---- } } // switch(tag) } // end of for } + void ClassFileParser::patch_class(ConstantPool* cp, int class_index, Klass* k, Symbol* name) { + int name_index = _orig_cp_size + _num_patched_klasses; + int resolved_klass_index = _first_patched_klass_resolved_index + _num_patched_klasses; + + cp->klass_at_put(class_index, name_index, resolved_klass_index, k, name); + _num_patched_klasses ++; + } + void ClassFileParser::patch_constant_pool(ConstantPool* cp, int index, Handle patch, TRAPS) { assert(cp != NULL, "invariant");
*** 716,732 **** // The name in the constant pool is ignored. if (java_lang_Class::is_instance(patch())) { 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_Klass(patch())); } else { guarantee_property(java_lang_String::is_instance(patch()), "Illegal class patch at %d in class file %s", index, CHECK); Symbol* const name = java_lang_String::as_symbol(patch(), CHECK); ! cp->unresolved_klass_at_put(index, name); } break; } case JVM_CONSTANT_String: { --- 736,753 ---- // The name in the constant pool is ignored. if (java_lang_Class::is_instance(patch())) { guarantee_property(!java_lang_Class::is_primitive(patch()), "Illegal class patch at %d in class file %s", index, CHECK); ! Klass* k = java_lang_Class::as_Klass(patch()); ! patch_class(cp, index, k, k->name()); } else { guarantee_property(java_lang_String::is_instance(patch()), "Illegal class patch at %d in class file %s", index, CHECK); Symbol* const name = java_lang_String::as_symbol(patch(), CHECK); ! patch_class(cp, index, NULL, name); } break; } case JVM_CONSTANT_String: {
*** 5338,5349 **** ik->set_initial_method_idnum(ik->methods()->length()); ik->set_name(_class_name); if (is_anonymous()) { ! // I am well known to myself ! ik->constants()->klass_at_put(_this_class_index, ik); // eagerly resolve } ik->set_minor_version(_minor_version); ik->set_major_version(_major_version); ik->set_has_nonstatic_concrete_methods(_has_nonstatic_concrete_methods); --- 5359,5376 ---- ik->set_initial_method_idnum(ik->methods()->length()); ik->set_name(_class_name); if (is_anonymous()) { ! // _this_class_index is a CONSTANT_Class entry that refers to this ! // anonymous class itself. If this class needs to refer to its own methods or ! // fields, it would use a CONSTANT_MethodRef, etc, which would reference ! // _this_class_index. However, because this class is anonymous (it's ! // not stored in SystemDictionary), _this_class_index cannot be resolved ! // with ConstantPool::klass_at_impl, which does a SystemDictionary lookup. ! // Therefore, we must eagerly resolve _this_class_index now. ! ik->constants()->klass_at_put(_this_class_index, ik); } ik->set_minor_version(_minor_version); ik->set_major_version(_major_version); ik->set_has_nonstatic_concrete_methods(_has_nonstatic_concrete_methods);
*** 5575,5584 **** --- 5602,5615 ---- _stream(stream), _requested_name(name), _loader_data(loader_data), _host_klass(host_klass), _cp_patches(cp_patches), + _num_patched_klasses(0), + _max_num_patched_klasses(0), + _orig_cp_size(0), + _first_patched_klass_resolved_index(0), _super_klass(), _cp(NULL), _fields(NULL), _methods(NULL), _inner_classes(NULL),
*** 5645,5654 **** --- 5676,5704 ---- } else { _need_verify = Verifier::should_verify_for(_loader_data->class_loader(), stream->need_verify()); } + if (_cp_patches != NULL) { + int len = _cp_patches->length(); + for (int i=0; i<len; i++) { + if (has_cp_patch_at(i)) { + Handle patch = cp_patch_at(i); + if (java_lang_String::is_instance(patch()) || java_lang_Class::is_instance(patch())) { + // We need to append the names of the patched classes to the end of the constant pool, + // because a patched class may have a Utf8 name that's not already included in the + // original constant pool. These class names are used when patch_constant_pool() + // calls patch_class(). + // + // Note that a String in cp_patch_at(i) may be used to patch a Utf8, a String, or a Class. + // At this point, we don't know the tag for index i yet, because we haven't parsed the + // constant pool. So we can only assume the worst -- every String is used to patch a Class. + _max_num_patched_klasses++; + } + } + } + } // synch back verification state to stream stream->set_verify(_need_verify); // Check if verification needs to be relaxed for this class file
*** 5774,5796 **** JAVA_MAX_SUPPORTED_MINOR_VERSION); return; } stream->guarantee_more(3, CHECK); // length, first cp tag ! const u2 cp_size = stream->get_u2_fast(); guarantee_property( cp_size >= 1, "Illegal constant pool size %u in class file %s", cp_size, CHECK); _cp = ConstantPool::allocate(_loader_data, cp_size, CHECK); ConstantPool* const cp = _cp; ! parse_constant_pool(stream, cp, cp_size, CHECK); assert(cp_size == (const u2)cp->length(), "invariant"); // ACCESS FLAGS stream->guarantee_more(8, CHECK); // flags, this_class, super_class, infs_len --- 5824,5852 ---- JAVA_MAX_SUPPORTED_MINOR_VERSION); return; } stream->guarantee_more(3, CHECK); // length, first cp tag ! u2 cp_size = stream->get_u2_fast(); guarantee_property( cp_size >= 1, "Illegal constant pool size %u in class file %s", cp_size, CHECK); + _orig_cp_size = cp_size; + if (int(cp_size) + _max_num_patched_klasses > 0xffff) { + THROW_MSG(vmSymbols::java_lang_InternalError(), "not enough space for patched classes"); + } + cp_size += _max_num_patched_klasses; + _cp = ConstantPool::allocate(_loader_data, cp_size, CHECK); ConstantPool* const cp = _cp; ! parse_constant_pool(stream, cp, _orig_cp_size, CHECK); assert(cp_size == (const u2)cp->length(), "invariant"); // ACCESS FLAGS stream->guarantee_more(8, CHECK); // flags, this_class, super_class, infs_len
< prev index next >