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