Merge
This commit is contained in:
commit
50a2f8c16d
@ -359,6 +359,12 @@ public class InstanceKlass extends Klass {
|
|||||||
public static final int innerClassNextOffset = 4;
|
public static final int innerClassNextOffset = 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static interface EnclosingMethodAttributeOffset {
|
||||||
|
public static final int enclosing_method_class_index_offset = 0;
|
||||||
|
public static final int enclosing_method_method_index_offset = 1;
|
||||||
|
public static final int enclosing_method_attribute_size = 2;
|
||||||
|
};
|
||||||
|
|
||||||
// refer to compute_modifier_flags in VM code.
|
// refer to compute_modifier_flags in VM code.
|
||||||
public long computeModifierFlags() {
|
public long computeModifierFlags() {
|
||||||
long access = getAccessFlags();
|
long access = getAccessFlags();
|
||||||
@ -367,9 +373,14 @@ public class InstanceKlass extends Klass {
|
|||||||
int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength();
|
int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength();
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
if (Assert.ASSERTS_ENABLED) {
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking");
|
Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||
|
||||||
|
length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size,
|
||||||
|
"just checking");
|
||||||
}
|
}
|
||||||
for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
|
for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
|
||||||
|
if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
int ioff = innerClassList.getShortAt(i +
|
int ioff = innerClassList.getShortAt(i +
|
||||||
InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
|
InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
|
||||||
// 'ioff' can be zero.
|
// 'ioff' can be zero.
|
||||||
@ -419,9 +430,14 @@ public class InstanceKlass extends Klass {
|
|||||||
int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength();
|
int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength();
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
if (Assert.ASSERTS_ENABLED) {
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking");
|
Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||
|
||||||
|
length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size,
|
||||||
|
"just checking");
|
||||||
}
|
}
|
||||||
for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
|
for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
|
||||||
|
if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
int ioff = innerClassList.getShortAt(i +
|
int ioff = innerClassList.getShortAt(i +
|
||||||
InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
|
InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
|
||||||
// 'ioff' can be zero.
|
// 'ioff' can be zero.
|
||||||
|
@ -2315,13 +2315,32 @@ void ClassFileParser::parse_classfile_source_debug_extension_attribute(constantP
|
|||||||
#define RECOGNIZED_INNER_CLASS_MODIFIERS (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC)
|
#define RECOGNIZED_INNER_CLASS_MODIFIERS (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC)
|
||||||
|
|
||||||
// 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(constantPoolHandle cp, instanceKlassHandle k, TRAPS) {
|
u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
|
||||||
|
bool parsed_enclosingmethod_attribute,
|
||||||
|
u2 enclosing_method_class_index,
|
||||||
|
u2 enclosing_method_method_index,
|
||||||
|
constantPoolHandle cp,
|
||||||
|
instanceKlassHandle k, TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
cfs->guarantee_more(2, CHECK_0); // length
|
u1* current_mark = cfs->current();
|
||||||
u2 length = cfs->get_u2_fast();
|
u2 length = 0;
|
||||||
|
if (inner_classes_attribute_start != NULL) {
|
||||||
|
cfs->set_current(inner_classes_attribute_start);
|
||||||
|
cfs->guarantee_more(2, CHECK_0); // length
|
||||||
|
length = cfs->get_u2_fast();
|
||||||
|
}
|
||||||
|
|
||||||
// 4-tuples of shorts [inner_class_info_index, outer_class_info_index, inner_name_index, inner_class_access_flags]
|
// 4-tuples of shorts of inner classes data and 2 shorts of enclosing
|
||||||
typeArrayOop ic = oopFactory::new_permanent_shortArray(length*4, CHECK_0);
|
// method data:
|
||||||
|
// [inner_class_info_index,
|
||||||
|
// outer_class_info_index,
|
||||||
|
// inner_name_index,
|
||||||
|
// inner_class_access_flags,
|
||||||
|
// ...
|
||||||
|
// enclosing_method_class_index,
|
||||||
|
// enclosing_method_method_index]
|
||||||
|
int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0);
|
||||||
|
typeArrayOop ic = oopFactory::new_permanent_shortArray(size, CHECK_0);
|
||||||
typeArrayHandle inner_classes(THREAD, ic);
|
typeArrayHandle inner_classes(THREAD, ic);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int cp_size = cp->length();
|
int cp_size = cp->length();
|
||||||
@ -2372,8 +2391,8 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(constantPoolHandle c
|
|||||||
|
|
||||||
// 4347400: make sure there's no duplicate entry in the classes array
|
// 4347400: make sure there's no duplicate entry in the classes array
|
||||||
if (_need_verify && _major_version >= JAVA_1_5_VERSION) {
|
if (_need_verify && _major_version >= JAVA_1_5_VERSION) {
|
||||||
for(int i = 0; i < inner_classes->length(); i += 4) {
|
for(int i = 0; i < length * 4; i += 4) {
|
||||||
for(int j = i + 4; j < inner_classes->length(); j += 4) {
|
for(int j = i + 4; j < length * 4; j += 4) {
|
||||||
guarantee_property((inner_classes->ushort_at(i) != inner_classes->ushort_at(j) ||
|
guarantee_property((inner_classes->ushort_at(i) != inner_classes->ushort_at(j) ||
|
||||||
inner_classes->ushort_at(i+1) != inner_classes->ushort_at(j+1) ||
|
inner_classes->ushort_at(i+1) != inner_classes->ushort_at(j+1) ||
|
||||||
inner_classes->ushort_at(i+2) != inner_classes->ushort_at(j+2) ||
|
inner_classes->ushort_at(i+2) != inner_classes->ushort_at(j+2) ||
|
||||||
@ -2384,8 +2403,19 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(constantPoolHandle c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set EnclosingMethod class and method indexes.
|
||||||
|
if (parsed_enclosingmethod_attribute) {
|
||||||
|
inner_classes->short_at_put(index++, enclosing_method_class_index);
|
||||||
|
inner_classes->short_at_put(index++, enclosing_method_method_index);
|
||||||
|
}
|
||||||
|
assert(index == size, "wrong size");
|
||||||
|
|
||||||
// Update instanceKlass with inner class info.
|
// Update instanceKlass with inner class info.
|
||||||
k->set_inner_classes(inner_classes());
|
k->set_inner_classes(inner_classes());
|
||||||
|
|
||||||
|
// Restore buffer's current position.
|
||||||
|
cfs->set_current(current_mark);
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2490,6 +2520,10 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
|
|||||||
int runtime_visible_annotations_length = 0;
|
int runtime_visible_annotations_length = 0;
|
||||||
u1* runtime_invisible_annotations = NULL;
|
u1* runtime_invisible_annotations = NULL;
|
||||||
int runtime_invisible_annotations_length = 0;
|
int runtime_invisible_annotations_length = 0;
|
||||||
|
u1* inner_classes_attribute_start = NULL;
|
||||||
|
u4 inner_classes_attribute_length = 0;
|
||||||
|
u2 enclosing_method_class_index = 0;
|
||||||
|
u2 enclosing_method_method_index = 0;
|
||||||
// Iterate over attributes
|
// Iterate over attributes
|
||||||
while (attributes_count--) {
|
while (attributes_count--) {
|
||||||
cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length
|
cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length
|
||||||
@ -2522,11 +2556,9 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
|
|||||||
} else {
|
} else {
|
||||||
parsed_innerclasses_attribute = true;
|
parsed_innerclasses_attribute = true;
|
||||||
}
|
}
|
||||||
u2 num_of_classes = parse_classfile_inner_classes_attribute(cp, k, CHECK);
|
inner_classes_attribute_start = cfs->get_u1_buffer();
|
||||||
if (_need_verify && _major_version >= JAVA_1_5_VERSION) {
|
inner_classes_attribute_length = attribute_length;
|
||||||
guarantee_property(attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes,
|
cfs->skip_u1(inner_classes_attribute_length, CHECK);
|
||||||
"Wrong InnerClasses attribute length in class file %s", CHECK);
|
|
||||||
}
|
|
||||||
} else if (tag == vmSymbols::tag_synthetic()) {
|
} else if (tag == vmSymbols::tag_synthetic()) {
|
||||||
// Check for Synthetic tag
|
// Check for Synthetic tag
|
||||||
// Shouldn't we check that the synthetic flags wasn't already set? - not required in spec
|
// Shouldn't we check that the synthetic flags wasn't already set? - not required in spec
|
||||||
@ -2568,22 +2600,21 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
|
|||||||
parsed_enclosingmethod_attribute = true;
|
parsed_enclosingmethod_attribute = true;
|
||||||
}
|
}
|
||||||
cfs->guarantee_more(4, CHECK); // class_index, method_index
|
cfs->guarantee_more(4, CHECK); // class_index, method_index
|
||||||
u2 class_index = cfs->get_u2_fast();
|
enclosing_method_class_index = cfs->get_u2_fast();
|
||||||
u2 method_index = cfs->get_u2_fast();
|
enclosing_method_method_index = cfs->get_u2_fast();
|
||||||
if (class_index == 0) {
|
if (enclosing_method_class_index == 0) {
|
||||||
classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", CHECK);
|
classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", CHECK);
|
||||||
}
|
}
|
||||||
// Validate the constant pool indices and types
|
// Validate the constant pool indices and types
|
||||||
if (!cp->is_within_bounds(class_index) ||
|
if (!cp->is_within_bounds(enclosing_method_class_index) ||
|
||||||
!is_klass_reference(cp, class_index)) {
|
!is_klass_reference(cp, enclosing_method_class_index)) {
|
||||||
classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK);
|
classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK);
|
||||||
}
|
}
|
||||||
if (method_index != 0 &&
|
if (enclosing_method_method_index != 0 &&
|
||||||
(!cp->is_within_bounds(method_index) ||
|
(!cp->is_within_bounds(enclosing_method_method_index) ||
|
||||||
!cp->tag_at(method_index).is_name_and_type())) {
|
!cp->tag_at(enclosing_method_method_index).is_name_and_type())) {
|
||||||
classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK);
|
classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK);
|
||||||
}
|
}
|
||||||
k->set_enclosing_method_indices(class_index, method_index);
|
|
||||||
} else if (tag == vmSymbols::tag_bootstrap_methods() &&
|
} else if (tag == vmSymbols::tag_bootstrap_methods() &&
|
||||||
_major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
|
_major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
|
||||||
if (parsed_bootstrap_methods_attribute)
|
if (parsed_bootstrap_methods_attribute)
|
||||||
@ -2606,6 +2637,20 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
|
|||||||
CHECK);
|
CHECK);
|
||||||
k->set_class_annotations(annotations());
|
k->set_class_annotations(annotations());
|
||||||
|
|
||||||
|
if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
|
||||||
|
u2 num_of_classes = parse_classfile_inner_classes_attribute(
|
||||||
|
inner_classes_attribute_start,
|
||||||
|
parsed_innerclasses_attribute,
|
||||||
|
enclosing_method_class_index,
|
||||||
|
enclosing_method_method_index,
|
||||||
|
cp, k, 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) {
|
if (_max_bootstrap_specifier_index >= 0) {
|
||||||
guarantee_property(parsed_bootstrap_methods_attribute,
|
guarantee_property(parsed_bootstrap_methods_attribute,
|
||||||
"Missing BootstrapMethods attribute in class file %s", CHECK);
|
"Missing BootstrapMethods attribute in class file %s", CHECK);
|
||||||
|
@ -130,7 +130,11 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
void parse_classfile_sourcefile_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
|
void parse_classfile_sourcefile_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
|
||||||
void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
|
void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
|
||||||
instanceKlassHandle k, int length, TRAPS);
|
instanceKlassHandle k, int length, TRAPS);
|
||||||
u2 parse_classfile_inner_classes_attribute(constantPoolHandle cp,
|
u2 parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
|
||||||
|
bool parsed_enclosingmethod_attribute,
|
||||||
|
u2 enclosing_method_class_index,
|
||||||
|
u2 enclosing_method_method_index,
|
||||||
|
constantPoolHandle cp,
|
||||||
instanceKlassHandle k, TRAPS);
|
instanceKlassHandle k, TRAPS);
|
||||||
void parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
|
void parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
|
||||||
void parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
|
void parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
|
||||||
|
@ -297,16 +297,14 @@ public:
|
|||||||
|
|
||||||
if (obj->blueprint()->oop_is_instanceKlass()) {
|
if (obj->blueprint()->oop_is_instanceKlass()) {
|
||||||
instanceKlass* ik = instanceKlass::cast((klassOop)obj);
|
instanceKlass* ik = instanceKlass::cast((klassOop)obj);
|
||||||
typeArrayOop inner_classes = ik->inner_classes();
|
instanceKlassHandle ik_h((klassOop)obj);
|
||||||
if (inner_classes != NULL) {
|
InnerClassesIterator iter(ik_h);
|
||||||
constantPoolOop constants = ik->constants();
|
constantPoolOop constants = ik->constants();
|
||||||
int n = inner_classes->length();
|
for (; !iter.done(); iter.next()) {
|
||||||
for (int i = 0; i < n; i += instanceKlass::inner_class_next_offset) {
|
int index = iter.inner_name_index();
|
||||||
int ioff = i + instanceKlass::inner_class_inner_name_offset;
|
|
||||||
int index = inner_classes->ushort_at(ioff);
|
if (index != 0) {
|
||||||
if (index != 0) {
|
_closure->do_symbol(constants->symbol_at_addr(index));
|
||||||
_closure->do_symbol(constants->symbol_at_addr(index));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1133,6 +1133,36 @@ JNIid* instanceKlass::jni_id_for(int offset) {
|
|||||||
return probe;
|
return probe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u2 instanceKlass::enclosing_method_data(int offset) {
|
||||||
|
typeArrayOop inner_class_list = inner_classes();
|
||||||
|
if (inner_class_list == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int length = inner_class_list->length();
|
||||||
|
if (length % inner_class_next_offset == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
int index = length - enclosing_method_attribute_size;
|
||||||
|
typeArrayHandle inner_class_list_h(inner_class_list);
|
||||||
|
assert(offset < enclosing_method_attribute_size, "invalid offset");
|
||||||
|
return inner_class_list_h->ushort_at(index + offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void instanceKlass::set_enclosing_method_indices(u2 class_index,
|
||||||
|
u2 method_index) {
|
||||||
|
typeArrayOop inner_class_list = inner_classes();
|
||||||
|
assert (inner_class_list != NULL, "_inner_classes list is not set up");
|
||||||
|
int length = inner_class_list->length();
|
||||||
|
if (length % inner_class_next_offset == enclosing_method_attribute_size) {
|
||||||
|
int index = length - enclosing_method_attribute_size;
|
||||||
|
typeArrayHandle inner_class_list_h(inner_class_list);
|
||||||
|
inner_class_list_h->ushort_at_put(
|
||||||
|
index + enclosing_method_class_index_offset, class_index);
|
||||||
|
inner_class_list_h->ushort_at_put(
|
||||||
|
index + enclosing_method_method_index_offset, method_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Lookup or create a jmethodID.
|
// Lookup or create a jmethodID.
|
||||||
// This code is called by the VMThread and JavaThreads so the
|
// This code is called by the VMThread and JavaThreads so the
|
||||||
@ -2107,28 +2137,21 @@ jint instanceKlass::compute_modifier_flags(TRAPS) const {
|
|||||||
jint access = access_flags().as_int();
|
jint access = access_flags().as_int();
|
||||||
|
|
||||||
// But check if it happens to be member class.
|
// But check if it happens to be member class.
|
||||||
typeArrayOop inner_class_list = inner_classes();
|
instanceKlassHandle ik(THREAD, k);
|
||||||
int length = (inner_class_list == NULL) ? 0 : inner_class_list->length();
|
InnerClassesIterator iter(ik);
|
||||||
assert (length % instanceKlass::inner_class_next_offset == 0, "just checking");
|
for (; !iter.done(); iter.next()) {
|
||||||
if (length > 0) {
|
int ioff = iter.inner_class_info_index();
|
||||||
typeArrayHandle inner_class_list_h(THREAD, inner_class_list);
|
// Inner class attribute can be zero, skip it.
|
||||||
instanceKlassHandle ik(THREAD, k);
|
// Strange but true: JVM spec. allows null inner class refs.
|
||||||
for (int i = 0; i < length; i += instanceKlass::inner_class_next_offset) {
|
if (ioff == 0) continue;
|
||||||
int ioff = inner_class_list_h->ushort_at(
|
|
||||||
i + instanceKlass::inner_class_inner_class_info_offset);
|
|
||||||
|
|
||||||
// Inner class attribute can be zero, skip it.
|
// only look at classes that are already loaded
|
||||||
// Strange but true: JVM spec. allows null inner class refs.
|
// since we are looking for the flags for our self.
|
||||||
if (ioff == 0) continue;
|
Symbol* inner_name = ik->constants()->klass_name_at(ioff);
|
||||||
|
if ((ik->name() == inner_name)) {
|
||||||
// only look at classes that are already loaded
|
// This is really a member class.
|
||||||
// since we are looking for the flags for our self.
|
access = iter.inner_access_flags();
|
||||||
Symbol* inner_name = ik->constants()->klass_name_at(ioff);
|
break;
|
||||||
if ((ik->name() == inner_name)) {
|
|
||||||
// This is really a member class.
|
|
||||||
access = inner_class_list_h->ushort_at(i + instanceKlass::inner_class_access_flags_offset);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remember to strip ACC_SUPER bit
|
// Remember to strip ACC_SUPER bit
|
||||||
|
@ -188,7 +188,17 @@ class instanceKlass: public Klass {
|
|||||||
klassOop _host_klass;
|
klassOop _host_klass;
|
||||||
// Class signers.
|
// Class signers.
|
||||||
objArrayOop _signers;
|
objArrayOop _signers;
|
||||||
// inner_classes attribute.
|
// The InnerClasses attribute and EnclosingMethod attribute. The
|
||||||
|
// _inner_classes is an array of shorts. If the class has InnerClasses
|
||||||
|
// attribute, then the _inner_classes array begins with 4-tuples of shorts
|
||||||
|
// [inner_class_info_index, outer_class_info_index,
|
||||||
|
// inner_name_index, inner_class_access_flags] for the InnerClasses
|
||||||
|
// attribute. If the EnclosingMethod attribute exists, it occupies the
|
||||||
|
// last two shorts [class_index, method_index] of the array. If only
|
||||||
|
// the InnerClasses attribute exists, the _inner_classes array length is
|
||||||
|
// number_of_inner_classes * 4. If the class has both InnerClasses
|
||||||
|
// and EnclosingMethod attributes the _inner_classes array length is
|
||||||
|
// number_of_inner_classes * 4 + enclosing_method_attribute_size.
|
||||||
typeArrayOop _inner_classes;
|
typeArrayOop _inner_classes;
|
||||||
// Implementors of this interface (not valid if it overflows)
|
// Implementors of this interface (not valid if it overflows)
|
||||||
klassOop _implementors[implementors_limit];
|
klassOop _implementors[implementors_limit];
|
||||||
@ -251,8 +261,6 @@ class instanceKlass: public Klass {
|
|||||||
// Array of interesting part(s) of the previous version(s) of this
|
// Array of interesting part(s) of the previous version(s) of this
|
||||||
// instanceKlass. See PreviousVersionWalker below.
|
// instanceKlass. See PreviousVersionWalker below.
|
||||||
GrowableArray<PreviousVersionNode *>* _previous_versions;
|
GrowableArray<PreviousVersionNode *>* _previous_versions;
|
||||||
u2 _enclosing_method_class_index; // Constant pool index for class of enclosing method, or 0 if none
|
|
||||||
u2 _enclosing_method_method_index; // Constant pool index for name and type of enclosing method, or 0 if none
|
|
||||||
// JVMTI fields can be moved to their own structure - see 6315920
|
// JVMTI fields can be moved to their own structure - see 6315920
|
||||||
unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH
|
unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH
|
||||||
jint _cached_class_file_len; // JVMTI: length of above
|
jint _cached_class_file_len; // JVMTI: length of above
|
||||||
@ -351,6 +359,12 @@ class instanceKlass: public Klass {
|
|||||||
inner_class_next_offset = 4
|
inner_class_next_offset = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum EnclosingMethodAttributeOffset {
|
||||||
|
enclosing_method_class_index_offset = 0,
|
||||||
|
enclosing_method_method_index_offset = 1,
|
||||||
|
enclosing_method_attribute_size = 2
|
||||||
|
};
|
||||||
|
|
||||||
// method override check
|
// method override check
|
||||||
bool is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
|
bool is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
|
||||||
|
|
||||||
@ -533,11 +547,15 @@ class instanceKlass: public Klass {
|
|||||||
Symbol* generic_signature() const { return _generic_signature; }
|
Symbol* generic_signature() const { return _generic_signature; }
|
||||||
void set_generic_signature(Symbol* sig) { _generic_signature = sig; }
|
void set_generic_signature(Symbol* sig) { _generic_signature = sig; }
|
||||||
|
|
||||||
u2 enclosing_method_class_index() const { return _enclosing_method_class_index; }
|
u2 enclosing_method_data(int offset);
|
||||||
u2 enclosing_method_method_index() const { return _enclosing_method_method_index; }
|
u2 enclosing_method_class_index() {
|
||||||
|
return enclosing_method_data(enclosing_method_class_index_offset);
|
||||||
|
}
|
||||||
|
u2 enclosing_method_method_index() {
|
||||||
|
return enclosing_method_data(enclosing_method_method_index_offset);
|
||||||
|
}
|
||||||
void set_enclosing_method_indices(u2 class_index,
|
void set_enclosing_method_indices(u2 class_index,
|
||||||
u2 method_index) { _enclosing_method_class_index = class_index;
|
u2 method_index);
|
||||||
_enclosing_method_method_index = method_index; }
|
|
||||||
|
|
||||||
// jmethodID support
|
// jmethodID support
|
||||||
static jmethodID get_jmethod_id(instanceKlassHandle ik_h,
|
static jmethodID get_jmethod_id(instanceKlassHandle ik_h,
|
||||||
@ -1053,4 +1071,83 @@ class nmethodBucket: public CHeapObj {
|
|||||||
nmethod* get_nmethod() { return _nmethod; }
|
nmethod* get_nmethod() { return _nmethod; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// An iterator that's used to access the inner classes indices in the
|
||||||
|
// instanceKlass::_inner_classes array.
|
||||||
|
class InnerClassesIterator : public StackObj {
|
||||||
|
private:
|
||||||
|
typeArrayHandle _inner_classes;
|
||||||
|
int _length;
|
||||||
|
int _idx;
|
||||||
|
public:
|
||||||
|
|
||||||
|
InnerClassesIterator(instanceKlassHandle k) {
|
||||||
|
_inner_classes = k->inner_classes();
|
||||||
|
if (k->inner_classes() != NULL) {
|
||||||
|
_length = _inner_classes->length();
|
||||||
|
// The inner class array's length should be the multiple of
|
||||||
|
// inner_class_next_offset if it only contains the InnerClasses
|
||||||
|
// attribute data, or it should be
|
||||||
|
// n*inner_class_next_offset+enclosing_method_attribute_size
|
||||||
|
// if it also contains the EnclosingMethod data.
|
||||||
|
assert((_length % instanceKlass::inner_class_next_offset == 0 ||
|
||||||
|
_length % instanceKlass::inner_class_next_offset == instanceKlass::enclosing_method_attribute_size),
|
||||||
|
"just checking");
|
||||||
|
// Remove the enclosing_method portion if exists.
|
||||||
|
if (_length % instanceKlass::inner_class_next_offset == instanceKlass::enclosing_method_attribute_size) {
|
||||||
|
_length -= instanceKlass::enclosing_method_attribute_size;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_length = 0;
|
||||||
|
}
|
||||||
|
_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length() const {
|
||||||
|
return _length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void next() {
|
||||||
|
_idx += instanceKlass::inner_class_next_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool done() const {
|
||||||
|
return (_idx >= _length);
|
||||||
|
}
|
||||||
|
|
||||||
|
u2 inner_class_info_index() const {
|
||||||
|
return _inner_classes->ushort_at(
|
||||||
|
_idx + instanceKlass::inner_class_inner_class_info_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_inner_class_info_index(u2 index) {
|
||||||
|
_inner_classes->ushort_at_put(
|
||||||
|
_idx + instanceKlass::inner_class_inner_class_info_offset, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
u2 outer_class_info_index() const {
|
||||||
|
return _inner_classes->ushort_at(
|
||||||
|
_idx + instanceKlass::inner_class_outer_class_info_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_outer_class_info_index(u2 index) {
|
||||||
|
_inner_classes->ushort_at_put(
|
||||||
|
_idx + instanceKlass::inner_class_outer_class_info_offset, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
u2 inner_name_index() const {
|
||||||
|
return _inner_classes->ushort_at(
|
||||||
|
_idx + instanceKlass::inner_class_inner_name_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_inner_name_index(u2 index) {
|
||||||
|
_inner_classes->ushort_at_put(
|
||||||
|
_idx + instanceKlass::inner_class_inner_name_offset, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
u2 inner_access_flags() const {
|
||||||
|
return _inner_classes->ushort_at(
|
||||||
|
_idx + instanceKlass::inner_class_access_flags_offset);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif // SHARE_VM_OOPS_INSTANCEKLASS_HPP
|
#endif // SHARE_VM_OOPS_INSTANCEKLASS_HPP
|
||||||
|
@ -416,7 +416,6 @@ instanceKlassKlass::allocate_instance_klass(Symbol* name, int vtable_len, int it
|
|||||||
ik->set_methods_annotations(NULL);
|
ik->set_methods_annotations(NULL);
|
||||||
ik->set_methods_parameter_annotations(NULL);
|
ik->set_methods_parameter_annotations(NULL);
|
||||||
ik->set_methods_default_annotations(NULL);
|
ik->set_methods_default_annotations(NULL);
|
||||||
ik->set_enclosing_method_indices(0, 0);
|
|
||||||
ik->set_jvmti_cached_class_field_map(NULL);
|
ik->set_jvmti_cached_class_field_map(NULL);
|
||||||
ik->set_initial_method_idnum(0);
|
ik->set_initial_method_idnum(0);
|
||||||
assert(k()->is_parsable(), "should be parsable here.");
|
assert(k()->is_parsable(), "should be parsable here.");
|
||||||
|
@ -1301,9 +1301,6 @@ JVM_END
|
|||||||
// Inner class reflection ///////////////////////////////////////////////////////////////////////////////
|
// Inner class reflection ///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass))
|
JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass))
|
||||||
const int inner_class_info_index = 0;
|
|
||||||
const int outer_class_info_index = 1;
|
|
||||||
|
|
||||||
JvmtiVMObjectAllocEventCollector oam;
|
JvmtiVMObjectAllocEventCollector oam;
|
||||||
// ofClass is a reference to a java_lang_Class object. The mirror object
|
// ofClass is a reference to a java_lang_Class object. The mirror object
|
||||||
// of an instanceKlass
|
// of an instanceKlass
|
||||||
@ -1315,26 +1312,26 @@ JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass))
|
|||||||
}
|
}
|
||||||
|
|
||||||
instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)));
|
instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)));
|
||||||
|
InnerClassesIterator iter(k);
|
||||||
|
|
||||||
if (k->inner_classes()->length() == 0) {
|
if (iter.length() == 0) {
|
||||||
// Neither an inner nor outer class
|
// Neither an inner nor outer class
|
||||||
oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL);
|
oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL);
|
||||||
return (jobjectArray)JNIHandles::make_local(env, result);
|
return (jobjectArray)JNIHandles::make_local(env, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// find inner class info
|
// find inner class info
|
||||||
typeArrayHandle icls(thread, k->inner_classes());
|
|
||||||
constantPoolHandle cp(thread, k->constants());
|
constantPoolHandle cp(thread, k->constants());
|
||||||
int length = icls->length();
|
int length = iter.length();
|
||||||
|
|
||||||
// Allocate temp. result array
|
// Allocate temp. result array
|
||||||
objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), length/4, CHECK_NULL);
|
objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), length/4, CHECK_NULL);
|
||||||
objArrayHandle result (THREAD, r);
|
objArrayHandle result (THREAD, r);
|
||||||
int members = 0;
|
int members = 0;
|
||||||
|
|
||||||
for(int i = 0; i < length; i += 4) {
|
for (; !iter.done(); iter.next()) {
|
||||||
int ioff = icls->ushort_at(i + inner_class_info_index);
|
int ioff = iter.inner_class_info_index();
|
||||||
int ooff = icls->ushort_at(i + outer_class_info_index);
|
int ooff = iter.outer_class_info_index();
|
||||||
|
|
||||||
if (ioff != 0 && ooff != 0) {
|
if (ioff != 0 && ooff != 0) {
|
||||||
// Check to see if the name matches the class we're looking for
|
// Check to see if the name matches the class we're looking for
|
||||||
@ -1392,17 +1389,13 @@ klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle k,
|
|||||||
bool* inner_is_member,
|
bool* inner_is_member,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
Thread* thread = THREAD;
|
Thread* thread = THREAD;
|
||||||
const int inner_class_info_index = inner_class_inner_class_info_offset;
|
InnerClassesIterator iter(k);
|
||||||
const int outer_class_info_index = inner_class_outer_class_info_offset;
|
if (iter.length() == 0) {
|
||||||
|
|
||||||
if (k->inner_classes()->length() == 0) {
|
|
||||||
// No inner class info => no declaring class
|
// No inner class info => no declaring class
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
typeArrayHandle i_icls(thread, k->inner_classes());
|
|
||||||
constantPoolHandle i_cp(thread, k->constants());
|
constantPoolHandle i_cp(thread, k->constants());
|
||||||
int i_length = i_icls->length();
|
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
klassOop ok;
|
klassOop ok;
|
||||||
@ -1410,10 +1403,10 @@ klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle k,
|
|||||||
*inner_is_member = false;
|
*inner_is_member = false;
|
||||||
|
|
||||||
// Find inner_klass attribute
|
// Find inner_klass attribute
|
||||||
for (int i = 0; i < i_length && !found; i += inner_class_next_offset) {
|
for (; !iter.done() && !found; iter.next()) {
|
||||||
int ioff = i_icls->ushort_at(i + inner_class_info_index);
|
int ioff = iter.inner_class_info_index();
|
||||||
int ooff = i_icls->ushort_at(i + outer_class_info_index);
|
int ooff = iter.outer_class_info_index();
|
||||||
int noff = i_icls->ushort_at(i + inner_class_inner_name_offset);
|
int noff = iter.inner_name_index();
|
||||||
if (ioff != 0) {
|
if (ioff != 0) {
|
||||||
// Check to see if the name matches the class we're looking for
|
// Check to see if the name matches the class we're looking for
|
||||||
// before attempting to find the class.
|
// before attempting to find the class.
|
||||||
|
@ -292,8 +292,8 @@ void JvmtiClassFileReconstituter::write_signature_attribute(u2 generic_signature
|
|||||||
|
|
||||||
// Compute the number of entries in the InnerClasses attribute
|
// Compute the number of entries in the InnerClasses attribute
|
||||||
u2 JvmtiClassFileReconstituter::inner_classes_attribute_length() {
|
u2 JvmtiClassFileReconstituter::inner_classes_attribute_length() {
|
||||||
typeArrayOop inner_class_list = ikh()->inner_classes();
|
InnerClassesIterator iter(ikh());
|
||||||
return (inner_class_list == NULL) ? 0 : inner_class_list->length();
|
return iter.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write an annotation attribute. The VM stores them in raw form, so all we need
|
// Write an annotation attribute. The VM stores them in raw form, so all we need
|
||||||
@ -324,26 +324,20 @@ void JvmtiClassFileReconstituter::write_annotations_attribute(const char* attr_n
|
|||||||
// JVMSpec| } classes[number_of_classes];
|
// JVMSpec| } classes[number_of_classes];
|
||||||
// JVMSpec| }
|
// JVMSpec| }
|
||||||
void JvmtiClassFileReconstituter::write_inner_classes_attribute(int length) {
|
void JvmtiClassFileReconstituter::write_inner_classes_attribute(int length) {
|
||||||
typeArrayOop inner_class_list = ikh()->inner_classes();
|
InnerClassesIterator iter(ikh());
|
||||||
guarantee(inner_class_list != NULL && inner_class_list->length() == length,
|
guarantee(iter.length() != 0 && iter.length() == length,
|
||||||
"caller must check");
|
"caller must check");
|
||||||
typeArrayHandle inner_class_list_h(thread(), inner_class_list);
|
|
||||||
assert (length % instanceKlass::inner_class_next_offset == 0, "just checking");
|
|
||||||
u2 entry_count = length / instanceKlass::inner_class_next_offset;
|
u2 entry_count = length / instanceKlass::inner_class_next_offset;
|
||||||
u4 size = 2 + entry_count * (2+2+2+2);
|
u4 size = 2 + entry_count * (2+2+2+2);
|
||||||
|
|
||||||
write_attribute_name_index("InnerClasses");
|
write_attribute_name_index("InnerClasses");
|
||||||
write_u4(size);
|
write_u4(size);
|
||||||
write_u2(entry_count);
|
write_u2(entry_count);
|
||||||
for (int i = 0; i < length; i += instanceKlass::inner_class_next_offset) {
|
for (; !iter.done(); iter.next()) {
|
||||||
write_u2(inner_class_list_h->ushort_at(
|
write_u2(iter.inner_class_info_index());
|
||||||
i + instanceKlass::inner_class_inner_class_info_offset));
|
write_u2(iter.outer_class_info_index());
|
||||||
write_u2(inner_class_list_h->ushort_at(
|
write_u2(iter.inner_name_index());
|
||||||
i + instanceKlass::inner_class_outer_class_info_offset));
|
write_u2(iter.inner_access_flags());
|
||||||
write_u2(inner_class_list_h->ushort_at(
|
|
||||||
i + instanceKlass::inner_class_inner_name_offset));
|
|
||||||
write_u2(inner_class_list_h->ushort_at(
|
|
||||||
i + instanceKlass::inner_class_access_flags_offset));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2400,44 +2400,33 @@ void VM_RedefineClasses::set_new_constant_pool(
|
|||||||
// new constant indices as needed. The inner classes info is a
|
// new constant indices as needed. The inner classes info is a
|
||||||
// quadruple:
|
// quadruple:
|
||||||
// (inner_class_info, outer_class_info, inner_name, inner_access_flags)
|
// (inner_class_info, outer_class_info, inner_name, inner_access_flags)
|
||||||
typeArrayOop inner_class_list = scratch_class->inner_classes();
|
InnerClassesIterator iter(scratch_class);
|
||||||
int icl_length = (inner_class_list == NULL) ? 0 : inner_class_list->length();
|
for (; !iter.done(); iter.next()) {
|
||||||
if (icl_length > 0) {
|
int cur_index = iter.inner_class_info_index();
|
||||||
typeArrayHandle inner_class_list_h(THREAD, inner_class_list);
|
if (cur_index == 0) {
|
||||||
for (int i = 0; i < icl_length;
|
continue; // JVM spec. allows null inner class refs so skip it
|
||||||
i += instanceKlass::inner_class_next_offset) {
|
}
|
||||||
int cur_index = inner_class_list_h->ushort_at(i
|
int new_index = find_new_index(cur_index);
|
||||||
+ instanceKlass::inner_class_inner_class_info_offset);
|
if (new_index != 0) {
|
||||||
if (cur_index == 0) {
|
RC_TRACE_WITH_THREAD(0x00080000, THREAD,
|
||||||
continue; // JVM spec. allows null inner class refs so skip it
|
("inner_class_info change: %d to %d", cur_index, new_index));
|
||||||
}
|
iter.set_inner_class_info_index(new_index);
|
||||||
int new_index = find_new_index(cur_index);
|
}
|
||||||
if (new_index != 0) {
|
cur_index = iter.outer_class_info_index();
|
||||||
RC_TRACE_WITH_THREAD(0x00080000, THREAD,
|
new_index = find_new_index(cur_index);
|
||||||
("inner_class_info change: %d to %d", cur_index, new_index));
|
if (new_index != 0) {
|
||||||
inner_class_list_h->ushort_at_put(i
|
RC_TRACE_WITH_THREAD(0x00080000, THREAD,
|
||||||
+ instanceKlass::inner_class_inner_class_info_offset, new_index);
|
("outer_class_info change: %d to %d", cur_index, new_index));
|
||||||
}
|
iter.set_outer_class_info_index(new_index);
|
||||||
cur_index = inner_class_list_h->ushort_at(i
|
}
|
||||||
+ instanceKlass::inner_class_outer_class_info_offset);
|
cur_index = iter.inner_name_index();
|
||||||
new_index = find_new_index(cur_index);
|
new_index = find_new_index(cur_index);
|
||||||
if (new_index != 0) {
|
if (new_index != 0) {
|
||||||
RC_TRACE_WITH_THREAD(0x00080000, THREAD,
|
RC_TRACE_WITH_THREAD(0x00080000, THREAD,
|
||||||
("outer_class_info change: %d to %d", cur_index, new_index));
|
("inner_name change: %d to %d", cur_index, new_index));
|
||||||
inner_class_list_h->ushort_at_put(i
|
iter.set_inner_name_index(new_index);
|
||||||
+ instanceKlass::inner_class_outer_class_info_offset, new_index);
|
}
|
||||||
}
|
} // end for each inner class
|
||||||
cur_index = inner_class_list_h->ushort_at(i
|
|
||||||
+ instanceKlass::inner_class_inner_name_offset);
|
|
||||||
new_index = find_new_index(cur_index);
|
|
||||||
if (new_index != 0) {
|
|
||||||
RC_TRACE_WITH_THREAD(0x00080000, THREAD,
|
|
||||||
("inner_name change: %d to %d", cur_index, new_index));
|
|
||||||
inner_class_list_h->ushort_at_put(i
|
|
||||||
+ instanceKlass::inner_class_inner_name_offset, new_index);
|
|
||||||
}
|
|
||||||
} // end for each inner class
|
|
||||||
} // end if we have inner classes
|
|
||||||
|
|
||||||
// Attach each method in klass to the new constant pool and update
|
// Attach each method in klass to the new constant pool and update
|
||||||
// to use new constant pool indices as needed:
|
// to use new constant pool indices as needed:
|
||||||
|
@ -591,14 +591,11 @@ bool Reflection::is_same_package_member(klassOop class1, klassOop class2, TRAPS)
|
|||||||
// Caller is responsible for figuring out in advance which case must be true.
|
// Caller is responsible for figuring out in advance which case must be true.
|
||||||
void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner,
|
void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner,
|
||||||
bool inner_is_member, TRAPS) {
|
bool inner_is_member, TRAPS) {
|
||||||
const int inner_class_info_index = 0;
|
InnerClassesIterator iter(outer);
|
||||||
const int outer_class_info_index = 1;
|
|
||||||
|
|
||||||
typeArrayHandle icls (THREAD, outer->inner_classes());
|
|
||||||
constantPoolHandle cp (THREAD, outer->constants());
|
constantPoolHandle cp (THREAD, outer->constants());
|
||||||
for(int i = 0; i < icls->length(); i += 4) {
|
for (; !iter.done(); iter.next()) {
|
||||||
int ioff = icls->ushort_at(i + inner_class_info_index);
|
int ioff = iter.inner_class_info_index();
|
||||||
int ooff = icls->ushort_at(i + outer_class_info_index);
|
int ooff = iter.outer_class_info_index();
|
||||||
|
|
||||||
if (inner_is_member && ioff != 0 && ooff != 0) {
|
if (inner_is_member && ioff != 0 && ooff != 0) {
|
||||||
klassOop o = cp->klass_at(ooff, CHECK);
|
klassOop o = cp->klass_at(ooff, CHECK);
|
||||||
|
Loading…
Reference in New Issue
Block a user