mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8243302: Advanced class supports
Co-authored-by: Harold Seigel <harold.seigel@oracle.com> Reviewed-by: coleenp, lfoltan, mschoene, rhalade
This commit is contained in:
parent
7eda1196c6
commit
29c68087c9
2 changed files with 94 additions and 11 deletions
|
@ -3121,8 +3121,83 @@ void ClassFileParser::parse_classfile_source_debug_extension_attribute(const Cla
|
||||||
JVM_ACC_STATIC \
|
JVM_ACC_STATIC \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Find index of the InnerClasses entry for the specified inner_class_info_index.
|
||||||
|
// Return -1 if none is found.
|
||||||
|
static int inner_classes_find_index(const Array<u2>* inner_classes, int inner, const ConstantPool* cp, int length) {
|
||||||
|
Symbol* cp_klass_name = cp->klass_name_at(inner);
|
||||||
|
for (int idx = 0; idx < length; idx += InstanceKlass::inner_class_next_offset) {
|
||||||
|
int idx_inner = inner_classes->at(idx + InstanceKlass::inner_class_inner_class_info_offset);
|
||||||
|
if (cp->klass_name_at(idx_inner) == cp_klass_name) {
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the outer_class_info_index for the InnerClasses entry containing the
|
||||||
|
// specified inner_class_info_index. Return -1 if no InnerClasses entry is found.
|
||||||
|
static int inner_classes_jump_to_outer(const Array<u2>* inner_classes, int inner, const ConstantPool* cp, int length) {
|
||||||
|
if (inner == 0) return -1;
|
||||||
|
int idx = inner_classes_find_index(inner_classes, inner, cp, length);
|
||||||
|
if (idx == -1) return -1;
|
||||||
|
int result = inner_classes->at(idx + InstanceKlass::inner_class_outer_class_info_offset);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if circularity is found, false if no circularity is found.
|
||||||
|
// Use Floyd's cycle finding algorithm.
|
||||||
|
static bool inner_classes_check_loop_through_outer(const Array<u2>* inner_classes, int idx, const ConstantPool* cp, int length) {
|
||||||
|
int slow = inner_classes->at(idx + InstanceKlass::inner_class_inner_class_info_offset);
|
||||||
|
int fast = inner_classes->at(idx + InstanceKlass::inner_class_outer_class_info_offset);
|
||||||
|
while (fast != -1 && fast != 0) {
|
||||||
|
if (slow != 0 && (cp->klass_name_at(slow) == cp->klass_name_at(fast))) {
|
||||||
|
return true; // found a circularity
|
||||||
|
}
|
||||||
|
fast = inner_classes_jump_to_outer(inner_classes, fast, cp, length);
|
||||||
|
if (fast == -1) return false;
|
||||||
|
fast = inner_classes_jump_to_outer(inner_classes, fast, cp, length);
|
||||||
|
if (fast == -1) return false;
|
||||||
|
slow = inner_classes_jump_to_outer(inner_classes, slow, cp, length);
|
||||||
|
assert(slow != -1, "sanity check");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through each InnerClasses entry checking for circularities and duplications
|
||||||
|
// with other entries. If duplicate entries are found then throw CFE. Otherwise,
|
||||||
|
// return true if a circularity or entries with duplicate inner_class_info_indexes
|
||||||
|
// are found.
|
||||||
|
bool ClassFileParser::check_inner_classes_circularity(const ConstantPool* cp, int length, TRAPS) {
|
||||||
|
// Loop through each InnerClasses entry.
|
||||||
|
for (int idx = 0; idx < length; idx += InstanceKlass::inner_class_next_offset) {
|
||||||
|
// Return true if there are circular entries.
|
||||||
|
if (inner_classes_check_loop_through_outer(_inner_classes, idx, cp, length)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Check if there are duplicate entries or entries with the same inner_class_info_index.
|
||||||
|
for (int y = idx + InstanceKlass::inner_class_next_offset; y < length;
|
||||||
|
y += InstanceKlass::inner_class_next_offset) {
|
||||||
|
|
||||||
|
// To maintain compatibility, throw an exception if duplicate inner classes
|
||||||
|
// entries are found.
|
||||||
|
guarantee_property((_inner_classes->at(idx) != _inner_classes->at(y) ||
|
||||||
|
_inner_classes->at(idx+1) != _inner_classes->at(y+1) ||
|
||||||
|
_inner_classes->at(idx+2) != _inner_classes->at(y+2) ||
|
||||||
|
_inner_classes->at(idx+3) != _inner_classes->at(y+3)),
|
||||||
|
"Duplicate entry in InnerClasses attribute in class file %s",
|
||||||
|
CHECK_(true));
|
||||||
|
// Return true if there are two entries with the same inner_class_info_index.
|
||||||
|
if (_inner_classes->at(y) == _inner_classes->at(idx)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Return number of classes in the inner classes attribute table
|
// Return number of classes in the inner classes attribute table
|
||||||
u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStream* const cfs,
|
u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStream* const cfs,
|
||||||
|
const ConstantPool* cp,
|
||||||
const u1* const inner_classes_attribute_start,
|
const u1* const inner_classes_attribute_start,
|
||||||
bool parsed_enclosingmethod_attribute,
|
bool parsed_enclosingmethod_attribute,
|
||||||
u2 enclosing_method_class_index,
|
u2 enclosing_method_class_index,
|
||||||
|
@ -3146,7 +3221,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStrea
|
||||||
// enclosing_method_class_index,
|
// enclosing_method_class_index,
|
||||||
// enclosing_method_method_index]
|
// enclosing_method_method_index]
|
||||||
const int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0);
|
const int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0);
|
||||||
Array<u2>* const inner_classes = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
|
Array<u2>* inner_classes = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
|
||||||
_inner_classes = inner_classes;
|
_inner_classes = inner_classes;
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
@ -3197,25 +3272,28 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStrea
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4347400: make sure there's no duplicate entry in the classes array
|
// 4347400: make sure there's no duplicate entry in the classes array
|
||||||
|
// Also, check for circular entries.
|
||||||
|
bool has_circularity = false;
|
||||||
if (_need_verify && _major_version >= JAVA_1_5_VERSION) {
|
if (_need_verify && _major_version >= JAVA_1_5_VERSION) {
|
||||||
for(int i = 0; i < length * 4; i += 4) {
|
has_circularity = check_inner_classes_circularity(cp, length * 4, CHECK_0);
|
||||||
for(int j = i + 4; j < length * 4; j += 4) {
|
if (has_circularity) {
|
||||||
guarantee_property((inner_classes->at(i) != inner_classes->at(j) ||
|
// If circularity check failed then ignore InnerClasses attribute.
|
||||||
inner_classes->at(i+1) != inner_classes->at(j+1) ||
|
MetadataFactory::free_array<u2>(_loader_data, _inner_classes);
|
||||||
inner_classes->at(i+2) != inner_classes->at(j+2) ||
|
index = 0;
|
||||||
inner_classes->at(i+3) != inner_classes->at(j+3)),
|
if (parsed_enclosingmethod_attribute) {
|
||||||
"Duplicate entry in InnerClasses in class file %s",
|
inner_classes = MetadataFactory::new_array<u2>(_loader_data, 2, CHECK_0);
|
||||||
CHECK_0);
|
_inner_classes = inner_classes;
|
||||||
|
} else {
|
||||||
|
_inner_classes = Universe::the_empty_short_array();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set EnclosingMethod class and method indexes.
|
// Set EnclosingMethod class and method indexes.
|
||||||
if (parsed_enclosingmethod_attribute) {
|
if (parsed_enclosingmethod_attribute) {
|
||||||
inner_classes->at_put(index++, enclosing_method_class_index);
|
inner_classes->at_put(index++, enclosing_method_class_index);
|
||||||
inner_classes->at_put(index++, enclosing_method_method_index);
|
inner_classes->at_put(index++, enclosing_method_method_index);
|
||||||
}
|
}
|
||||||
assert(index == size, "wrong size");
|
assert(index == size || has_circularity, "wrong size");
|
||||||
|
|
||||||
// Restore buffer's current position.
|
// Restore buffer's current position.
|
||||||
cfs->set_current(current_mark);
|
cfs->set_current(current_mark);
|
||||||
|
@ -3908,6 +3986,7 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf
|
||||||
if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
|
if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
|
||||||
const u2 num_of_classes = parse_classfile_inner_classes_attribute(
|
const u2 num_of_classes = parse_classfile_inner_classes_attribute(
|
||||||
cfs,
|
cfs,
|
||||||
|
cp,
|
||||||
inner_classes_attribute_start,
|
inner_classes_attribute_start,
|
||||||
parsed_innerclasses_attribute,
|
parsed_innerclasses_attribute,
|
||||||
enclosing_method_class_index,
|
enclosing_method_class_index,
|
||||||
|
|
|
@ -317,7 +317,11 @@ class ClassFileParser {
|
||||||
int length,
|
int length,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
|
||||||
|
// Check for circularity in InnerClasses attribute.
|
||||||
|
bool check_inner_classes_circularity(const ConstantPool* cp, int length, TRAPS);
|
||||||
|
|
||||||
u2 parse_classfile_inner_classes_attribute(const ClassFileStream* const cfs,
|
u2 parse_classfile_inner_classes_attribute(const ClassFileStream* const cfs,
|
||||||
|
const ConstantPool* cp,
|
||||||
const u1* const inner_classes_attribute_start,
|
const u1* const inner_classes_attribute_start,
|
||||||
bool parsed_enclosingmethod_attribute,
|
bool parsed_enclosingmethod_attribute,
|
||||||
u2 enclosing_method_class_index,
|
u2 enclosing_method_class_index,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue