< prev index next >
src/hotspot/share/classfile/classFileParser.cpp
Print this page
rev 50604 : imported patch jep181-rev1
rev 50606 : imported patch jep181-rev3
*** 3144,3154 ****
const int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0);
Array<u2>* const inner_classes = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
_inner_classes = inner_classes;
int index = 0;
- const int cp_size = _cp->length();
cfs->guarantee_more(8 * length, CHECK_0); // 4-tuples of u2
for (int n = 0; n < length; n++) {
// Inner class index
const u2 inner_class_info_index = cfs->get_u2_fast();
check_property(
--- 3144,3153 ----
*** 3218,3227 ****
--- 3217,3258 ----
cfs->set_current(current_mark);
return length;
}
+ u2 ClassFileParser::parse_classfile_nest_members_attribute(const ClassFileStream* const cfs,
+ const u1* const nest_members_attribute_start,
+ TRAPS) {
+ const u1* const current_mark = cfs->current();
+ u2 length = 0;
+ if (nest_members_attribute_start != NULL) {
+ cfs->set_current(nest_members_attribute_start);
+ cfs->guarantee_more(2, CHECK_0); // length
+ length = cfs->get_u2_fast();
+ }
+ const int size = length;
+ Array<u2>* const nest_members = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
+ _nest_members = nest_members;
+
+ int index = 0;
+ cfs->guarantee_more(2 * length, CHECK_0);
+ for (int n = 0; n < length; n++) {
+ const u2 class_info_index = cfs->get_u2_fast();
+ check_property(
+ valid_klass_reference_at(class_info_index),
+ "Nest member class_info_index %u has bad constant type in class file %s",
+ class_info_index, CHECK_0);
+ nest_members->at_put(index++, class_info_index);
+ }
+ assert(index == size, "wrong size");
+
+ // Restore buffer's current position.
+ cfs->set_current(current_mark);
+
+ return length;
+ }
+
void ClassFileParser::parse_classfile_synthetic_attribute(TRAPS) {
set_class_synthetic_flag(true);
}
void ClassFileParser::parse_classfile_signature_attribute(const ClassFileStream* const cfs, TRAPS) {
*** 3325,3338 ****
--- 3356,3373 ----
assert(cp != NULL, "invariant");
assert(parsed_annotations != NULL, "invariant");
// Set inner classes attribute to default sentinel
_inner_classes = Universe::the_empty_short_array();
+ // Set nest members attribute to default sentinel
+ _nest_members = Universe::the_empty_short_array();
cfs->guarantee_more(2, CHECK); // attributes_count
u2 attributes_count = cfs->get_u2_fast();
bool parsed_sourcefile_attribute = false;
bool parsed_innerclasses_attribute = false;
+ bool parsed_nest_members_attribute = false;
+ bool parsed_nest_host_attribute = false;
bool parsed_enclosingmethod_attribute = false;
bool parsed_bootstrap_methods_attribute = false;
const u1* runtime_visible_annotations = NULL;
int runtime_visible_annotations_length = 0;
const u1* runtime_invisible_annotations = NULL;
*** 3346,3355 ****
--- 3381,3393 ----
bool parsed_source_debug_ext_annotations_exist = false;
const u1* inner_classes_attribute_start = NULL;
u4 inner_classes_attribute_length = 0;
u2 enclosing_method_class_index = 0;
u2 enclosing_method_method_index = 0;
+ const u1* nest_members_attribute_start = NULL;
+ u4 nest_members_attribute_length = 0;
+
// Iterate over attributes
while (attributes_count--) {
cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length
const u2 attribute_name_index = cfs->get_u2_fast();
const u4 attribute_length = cfs->get_u4_fast();
*** 3494,3503 ****
--- 3532,3575 ----
runtime_invisible_type_annotations_length = attribute_length;
runtime_invisible_type_annotations = cfs->current();
assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations");
}
cfs->skip_u1(attribute_length, CHECK);
+ } else if (_major_version >= JAVA_11_VERSION) {
+ if (tag == vmSymbols::tag_nest_members()) {
+ // Check for NestMembers tag
+ if (parsed_nest_members_attribute) {
+ classfile_parse_error("Multiple NestMembers attributes in class file %s", CHECK);
+ } else {
+ parsed_nest_members_attribute = true;
+ }
+ if (parsed_nest_host_attribute) {
+ classfile_parse_error("Conflicting NestHost and NestMembers attributes in class file %s", CHECK);
+ }
+ nest_members_attribute_start = cfs->current();
+ nest_members_attribute_length = attribute_length;
+ cfs->skip_u1(nest_members_attribute_length, CHECK);
+ } else if (tag == vmSymbols::tag_nest_host()) {
+ if (parsed_nest_host_attribute) {
+ classfile_parse_error("Multiple NestHost attributes in class file %s", CHECK);
+ } else {
+ parsed_nest_host_attribute = true;
+ }
+ if (parsed_nest_members_attribute) {
+ classfile_parse_error("Conflicting NestMembers and NestHost attributes in class file %s", CHECK);
+ }
+ if (_need_verify) {
+ guarantee_property(attribute_length == 2, "Wrong NestHost attribute length in class file %s", CHECK);
+ }
+ cfs->guarantee_more(2, CHECK);
+ u2 class_info_index = cfs->get_u2_fast();
+ check_property(
+ valid_klass_reference_at(class_info_index),
+ "Nest-host class_info_index %u has bad constant type in class file %s",
+ class_info_index, CHECK);
+ _nest_host = class_info_index;
+ }
} else {
// Unknown attribute
cfs->skip_u1(attribute_length, CHECK);
}
} else {
*** 3522,3538 ****
inner_classes_attribute_start,
parsed_innerclasses_attribute,
enclosing_method_class_index,
enclosing_method_method_index,
CHECK);
! if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) {
guarantee_property(
inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes,
"Wrong InnerClasses attribute length in class file %s", CHECK);
}
}
if (_max_bootstrap_specifier_index >= 0) {
guarantee_property(parsed_bootstrap_methods_attribute,
"Missing BootstrapMethods attribute in class file %s", CHECK);
}
}
--- 3594,3622 ----
inner_classes_attribute_start,
parsed_innerclasses_attribute,
enclosing_method_class_index,
enclosing_method_method_index,
CHECK);
! if (parsed_innerclasses_attribute && _need_verify && _major_version >= JAVA_1_5_VERSION) {
guarantee_property(
inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes,
"Wrong InnerClasses attribute length in class file %s", CHECK);
}
}
+ if (parsed_nest_members_attribute) {
+ const u2 num_of_classes = parse_classfile_nest_members_attribute(
+ cfs,
+ nest_members_attribute_start,
+ CHECK);
+ if (_need_verify) {
+ guarantee_property(
+ nest_members_attribute_length == sizeof(num_of_classes) + sizeof(u2) * num_of_classes,
+ "Wrong NestMembers attribute length in class file %s", CHECK);
+ }
+ }
+
if (_max_bootstrap_specifier_index >= 0) {
guarantee_property(parsed_bootstrap_methods_attribute,
"Missing BootstrapMethods attribute in class file %s", CHECK);
}
}
*** 3591,3600 ****
--- 3675,3686 ----
_cp->set_pool_holder(this_klass);
this_klass->set_constants(_cp);
this_klass->set_fields(_fields, java_fields_count);
this_klass->set_methods(_methods);
this_klass->set_inner_classes(_inner_classes);
+ this_klass->set_nest_members(_nest_members);
+ this_klass->set_nest_host_index(_nest_host);
this_klass->set_local_interfaces(_local_interfaces);
this_klass->set_annotations(_combined_annotations);
// Delay the setting of _transitive_interfaces until after initialize_supers() in
// fill_instance_klass(). It is because the _transitive_interfaces may be shared with
// its _super. If an OOM occurs while loading the current klass, its _super field
*** 4601,4629 ****
if (super_m == NULL) {
break; // didn't find any match; get out
}
if (super_m->is_final() && !super_m->is_static() &&
! // matching method in super is final, and not static
! (Reflection::verify_field_access(this_klass,
super_m->method_holder(),
super_m->method_holder(),
! super_m->access_flags(), false))
// this class can access super final method and therefore override
- ) {
ResourceMark rm(THREAD);
! Exceptions::fthrow(
! THREAD_AND_LOCATION,
vmSymbols::java_lang_VerifyError(),
"class %s overrides final method %s.%s%s",
this_klass->external_name(),
super_m->method_holder()->external_name(),
name->as_C_string(),
signature->as_C_string()
);
return;
}
// continue to look from super_m's holder's super.
k = super_m->method_holder()->super();
continue;
}
--- 4687,4717 ----
if (super_m == NULL) {
break; // didn't find any match; get out
}
if (super_m->is_final() && !super_m->is_static() &&
! !super_m->access_flags().is_private()) {
! // matching method in super is final, and not static or private
! bool can_access = Reflection::verify_member_access(this_klass,
super_m->method_holder(),
super_m->method_holder(),
! super_m->access_flags(),
! false, false, CHECK);
! if (can_access) {
// this class can access super final method and therefore override
ResourceMark rm(THREAD);
! Exceptions::fthrow(THREAD_AND_LOCATION,
vmSymbols::java_lang_VerifyError(),
"class %s overrides final method %s.%s%s",
this_klass->external_name(),
super_m->method_holder()->external_name(),
name->as_C_string(),
signature->as_C_string()
);
return;
}
+ }
// continue to look from super_m's holder's super.
k = super_m->method_holder()->super();
continue;
}
*** 5466,5475 ****
--- 5554,5564 ----
// note that is not safe to use the fields in the parser from this point on
assert(NULL == _cp, "invariant");
assert(NULL == _fields, "invariant");
assert(NULL == _methods, "invariant");
assert(NULL == _inner_classes, "invariant");
+ assert(NULL == _nest_members, "invariant");
assert(NULL == _local_interfaces, "invariant");
assert(NULL == _combined_annotations, "invariant");
if (_has_final_method) {
ik->set_has_final_method();
*** 5735,5744 ****
--- 5824,5835 ----
_super_klass(),
_cp(NULL),
_fields(NULL),
_methods(NULL),
_inner_classes(NULL),
+ _nest_members(NULL),
+ _nest_host(0),
_local_interfaces(NULL),
_transitive_interfaces(NULL),
_combined_annotations(NULL),
_annotations(NULL),
_type_annotations(NULL),
*** 5839,5848 ****
--- 5930,5940 ----
// deallocated if classfile parsing returns an error.
_cp = NULL;
_fields = NULL;
_methods = NULL;
_inner_classes = NULL;
+ _nest_members = NULL;
_local_interfaces = NULL;
_combined_annotations = NULL;
_annotations = _type_annotations = NULL;
_fields_annotations = _fields_type_annotations = NULL;
}
*** 5864,5873 ****
--- 5956,5969 ----
// beware of the Universe::empty_blah_array!!
if (_inner_classes != NULL && _inner_classes != Universe::the_empty_short_array()) {
MetadataFactory::free_array<u2>(_loader_data, _inner_classes);
}
+ if (_nest_members != NULL && _nest_members != Universe::the_empty_short_array()) {
+ MetadataFactory::free_array<u2>(_loader_data, _nest_members);
+ }
+
// Free interfaces
InstanceKlass::deallocate_interfaces(_loader_data, _super_klass,
_local_interfaces, _transitive_interfaces);
if (_combined_annotations != NULL) {
< prev index next >