# HG changeset patch # User dlong # Date 1332713332 14400 # Node ID 0698f5ef55357e00bda648526a8edbb7116fd2d3 # Parent bc8881f974b80066d1b2d10a73a9250dfa315b56# Parent 6522ad563f99dce88a2e323ae1ffb26af04f2786 Merge diff -r bc8881f974b8 -r 0698f5ef5535 agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Mar 23 22:34:22 2012 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Sun Mar 25 18:08:52 2012 -0400 @@ -359,6 +359,12 @@ 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. public long computeModifierFlags() { long access = getAccessFlags(); @@ -367,9 +373,14 @@ int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength(); if (length > 0) { 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) { + if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) { + break; + } int ioff = innerClassList.getShortAt(i + InnerClassAttributeOffset.innerClassInnerClassInfoOffset); // 'ioff' can be zero. @@ -419,9 +430,14 @@ int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength(); if (length > 0) { 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) { + if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) { + break; + } int ioff = innerClassList.getShortAt(i + InnerClassAttributeOffset.innerClassInnerClassInfoOffset); // 'ioff' can be zero. diff -r bc8881f974b8 -r 0698f5ef5535 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Fri Mar 23 22:34:22 2012 -0700 +++ b/src/share/vm/classfile/classFileParser.cpp Sun Mar 25 18:08:52 2012 -0400 @@ -2315,13 +2315,32 @@ #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 -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(); - cfs->guarantee_more(2, CHECK_0); // length - u2 length = cfs->get_u2_fast(); - - // 4-tuples of shorts [inner_class_info_index, outer_class_info_index, inner_name_index, inner_class_access_flags] - typeArrayOop ic = oopFactory::new_permanent_shortArray(length*4, CHECK_0); + u1* current_mark = cfs->current(); + 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 of inner classes data and 2 shorts of enclosing + // 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); int index = 0; int cp_size = cp->length(); @@ -2372,8 +2391,8 @@ // 4347400: make sure there's no duplicate entry in the classes array if (_need_verify && _major_version >= JAVA_1_5_VERSION) { - for(int i = 0; i < inner_classes->length(); i += 4) { - for(int j = i + 4; j < inner_classes->length(); j += 4) { + for(int i = 0; i < length * 4; i += 4) { + for(int j = i + 4; j < length * 4; j += 4) { 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+2) != inner_classes->ushort_at(j+2) || @@ -2384,8 +2403,19 @@ } } + // 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. k->set_inner_classes(inner_classes()); + + // Restore buffer's current position. + cfs->set_current(current_mark); + return length; } @@ -2490,6 +2520,10 @@ int runtime_visible_annotations_length = 0; u1* runtime_invisible_annotations = NULL; 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 while (attributes_count--) { cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length @@ -2522,11 +2556,9 @@ } else { parsed_innerclasses_attribute = true; } - u2 num_of_classes = parse_classfile_inner_classes_attribute(cp, k, CHECK); - if (_need_verify && _major_version >= JAVA_1_5_VERSION) { - guarantee_property(attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes, - "Wrong InnerClasses attribute length in class file %s", CHECK); - } + inner_classes_attribute_start = cfs->get_u1_buffer(); + inner_classes_attribute_length = attribute_length; + cfs->skip_u1(inner_classes_attribute_length, CHECK); } else if (tag == vmSymbols::tag_synthetic()) { // Check for Synthetic tag // Shouldn't we check that the synthetic flags wasn't already set? - not required in spec @@ -2568,22 +2600,21 @@ parsed_enclosingmethod_attribute = true; } cfs->guarantee_more(4, CHECK); // class_index, method_index - u2 class_index = cfs->get_u2_fast(); - u2 method_index = cfs->get_u2_fast(); - if (class_index == 0) { + enclosing_method_class_index = cfs->get_u2_fast(); + enclosing_method_method_index = cfs->get_u2_fast(); + if (enclosing_method_class_index == 0) { classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", CHECK); } // Validate the constant pool indices and types - if (!cp->is_within_bounds(class_index) || - !is_klass_reference(cp, class_index)) { + if (!cp->is_within_bounds(enclosing_method_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); } - if (method_index != 0 && - (!cp->is_within_bounds(method_index) || - !cp->tag_at(method_index).is_name_and_type())) { + if (enclosing_method_method_index != 0 && + (!cp->is_within_bounds(enclosing_method_method_index) || + !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); } - k->set_enclosing_method_indices(class_index, method_index); } else if (tag == vmSymbols::tag_bootstrap_methods() && _major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { if (parsed_bootstrap_methods_attribute) @@ -2606,6 +2637,20 @@ CHECK); 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) { guarantee_property(parsed_bootstrap_methods_attribute, "Missing BootstrapMethods attribute in class file %s", CHECK); diff -r bc8881f974b8 -r 0698f5ef5535 src/share/vm/classfile/classFileParser.hpp --- a/src/share/vm/classfile/classFileParser.hpp Fri Mar 23 22:34:22 2012 -0700 +++ b/src/share/vm/classfile/classFileParser.hpp Sun Mar 25 18:08:52 2012 -0400 @@ -130,7 +130,11 @@ void parse_classfile_sourcefile_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS); void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp, 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); void parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS); void parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS); diff -r bc8881f974b8 -r 0698f5ef5535 src/share/vm/memory/dump.cpp --- a/src/share/vm/memory/dump.cpp Fri Mar 23 22:34:22 2012 -0700 +++ b/src/share/vm/memory/dump.cpp Sun Mar 25 18:08:52 2012 -0400 @@ -297,16 +297,14 @@ if (obj->blueprint()->oop_is_instanceKlass()) { instanceKlass* ik = instanceKlass::cast((klassOop)obj); - typeArrayOop inner_classes = ik->inner_classes(); - if (inner_classes != NULL) { - constantPoolOop constants = ik->constants(); - int n = inner_classes->length(); - for (int i = 0; i < n; i += instanceKlass::inner_class_next_offset) { - int ioff = i + instanceKlass::inner_class_inner_name_offset; - int index = inner_classes->ushort_at(ioff); - if (index != 0) { - _closure->do_symbol(constants->symbol_at_addr(index)); - } + instanceKlassHandle ik_h((klassOop)obj); + InnerClassesIterator iter(ik_h); + constantPoolOop constants = ik->constants(); + for (; !iter.done(); iter.next()) { + int index = iter.inner_name_index(); + + if (index != 0) { + _closure->do_symbol(constants->symbol_at_addr(index)); } } } diff -r bc8881f974b8 -r 0698f5ef5535 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Fri Mar 23 22:34:22 2012 -0700 +++ b/src/share/vm/oops/instanceKlass.cpp Sun Mar 25 18:08:52 2012 -0400 @@ -1133,6 +1133,36 @@ 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. // This code is called by the VMThread and JavaThreads so the @@ -2107,28 +2137,21 @@ jint access = access_flags().as_int(); // But check if it happens to be member class. - typeArrayOop inner_class_list = inner_classes(); - int length = (inner_class_list == NULL) ? 0 : inner_class_list->length(); - assert (length % instanceKlass::inner_class_next_offset == 0, "just checking"); - if (length > 0) { - typeArrayHandle inner_class_list_h(THREAD, inner_class_list); - instanceKlassHandle ik(THREAD, k); - for (int i = 0; i < length; i += instanceKlass::inner_class_next_offset) { - int ioff = inner_class_list_h->ushort_at( - i + instanceKlass::inner_class_inner_class_info_offset); - - // Inner class attribute can be zero, skip it. - // Strange but true: JVM spec. allows null inner class refs. - if (ioff == 0) continue; - - // only look at classes that are already loaded - // since we are looking for the flags for our self. - Symbol* inner_name = ik->constants()->klass_name_at(ioff); - 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; - } + instanceKlassHandle ik(THREAD, k); + InnerClassesIterator iter(ik); + for (; !iter.done(); iter.next()) { + int ioff = iter.inner_class_info_index(); + // Inner class attribute can be zero, skip it. + // Strange but true: JVM spec. allows null inner class refs. + if (ioff == 0) continue; + + // only look at classes that are already loaded + // since we are looking for the flags for our self. + Symbol* inner_name = ik->constants()->klass_name_at(ioff); + if ((ik->name() == inner_name)) { + // This is really a member class. + access = iter.inner_access_flags(); + break; } } // Remember to strip ACC_SUPER bit diff -r bc8881f974b8 -r 0698f5ef5535 src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Fri Mar 23 22:34:22 2012 -0700 +++ b/src/share/vm/oops/instanceKlass.hpp Sun Mar 25 18:08:52 2012 -0400 @@ -188,7 +188,17 @@ klassOop _host_klass; // Class 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; // Implementors of this interface (not valid if it overflows) klassOop _implementors[implementors_limit]; @@ -251,8 +261,6 @@ // Array of interesting part(s) of the previous version(s) of this // instanceKlass. See PreviousVersionWalker below. GrowableArray* _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 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 @@ -351,6 +359,12 @@ 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 bool is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS); @@ -533,11 +547,15 @@ Symbol* generic_signature() const { return _generic_signature; } void set_generic_signature(Symbol* sig) { _generic_signature = sig; } - u2 enclosing_method_class_index() const { return _enclosing_method_class_index; } - u2 enclosing_method_method_index() const { return _enclosing_method_method_index; } + u2 enclosing_method_data(int offset); + 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, - u2 method_index) { _enclosing_method_class_index = class_index; - _enclosing_method_method_index = method_index; } + u2 method_index); // jmethodID support static jmethodID get_jmethod_id(instanceKlassHandle ik_h, @@ -1053,4 +1071,83 @@ 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 diff -r bc8881f974b8 -r 0698f5ef5535 src/share/vm/oops/instanceKlassKlass.cpp --- a/src/share/vm/oops/instanceKlassKlass.cpp Fri Mar 23 22:34:22 2012 -0700 +++ b/src/share/vm/oops/instanceKlassKlass.cpp Sun Mar 25 18:08:52 2012 -0400 @@ -416,7 +416,6 @@ ik->set_methods_annotations(NULL); ik->set_methods_parameter_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_initial_method_idnum(0); assert(k()->is_parsable(), "should be parsable here."); diff -r bc8881f974b8 -r 0698f5ef5535 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Fri Mar 23 22:34:22 2012 -0700 +++ b/src/share/vm/prims/jvm.cpp Sun Mar 25 18:08:52 2012 -0400 @@ -1301,9 +1301,6 @@ // Inner class reflection /////////////////////////////////////////////////////////////////////////////// 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; // ofClass is a reference to a java_lang_Class object. The mirror object // of an instanceKlass @@ -1315,26 +1312,26 @@ } instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass))); - - if (k->inner_classes()->length() == 0) { + InnerClassesIterator iter(k); + + if (iter.length() == 0) { // Neither an inner nor outer class oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); return (jobjectArray)JNIHandles::make_local(env, result); } // find inner class info - typeArrayHandle icls(thread, k->inner_classes()); constantPoolHandle cp(thread, k->constants()); - int length = icls->length(); + int length = iter.length(); // Allocate temp. result array objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), length/4, CHECK_NULL); objArrayHandle result (THREAD, r); int members = 0; - for(int i = 0; i < length; i += 4) { - int ioff = icls->ushort_at(i + inner_class_info_index); - int ooff = icls->ushort_at(i + outer_class_info_index); + for (; !iter.done(); iter.next()) { + int ioff = iter.inner_class_info_index(); + int ooff = iter.outer_class_info_index(); if (ioff != 0 && ooff != 0) { // Check to see if the name matches the class we're looking for @@ -1392,17 +1389,13 @@ bool* inner_is_member, TRAPS) { Thread* thread = THREAD; - const int inner_class_info_index = inner_class_inner_class_info_offset; - const int outer_class_info_index = inner_class_outer_class_info_offset; - - if (k->inner_classes()->length() == 0) { + InnerClassesIterator iter(k); + if (iter.length() == 0) { // No inner class info => no declaring class return NULL; } - typeArrayHandle i_icls(thread, k->inner_classes()); constantPoolHandle i_cp(thread, k->constants()); - int i_length = i_icls->length(); bool found = false; klassOop ok; @@ -1410,10 +1403,10 @@ *inner_is_member = false; // Find inner_klass attribute - for (int i = 0; i < i_length && !found; i += inner_class_next_offset) { - int ioff = i_icls->ushort_at(i + inner_class_info_index); - int ooff = i_icls->ushort_at(i + outer_class_info_index); - int noff = i_icls->ushort_at(i + inner_class_inner_name_offset); + for (; !iter.done() && !found; iter.next()) { + int ioff = iter.inner_class_info_index(); + int ooff = iter.outer_class_info_index(); + int noff = iter.inner_name_index(); if (ioff != 0) { // Check to see if the name matches the class we're looking for // before attempting to find the class. diff -r bc8881f974b8 -r 0698f5ef5535 src/share/vm/prims/jvmtiClassFileReconstituter.cpp --- a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Fri Mar 23 22:34:22 2012 -0700 +++ b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Sun Mar 25 18:08:52 2012 -0400 @@ -292,8 +292,8 @@ // Compute the number of entries in the InnerClasses attribute u2 JvmtiClassFileReconstituter::inner_classes_attribute_length() { - typeArrayOop inner_class_list = ikh()->inner_classes(); - return (inner_class_list == NULL) ? 0 : inner_class_list->length(); + InnerClassesIterator iter(ikh()); + return iter.length(); } // Write an annotation attribute. The VM stores them in raw form, so all we need @@ -324,26 +324,20 @@ // JVMSpec| } classes[number_of_classes]; // JVMSpec| } void JvmtiClassFileReconstituter::write_inner_classes_attribute(int length) { - typeArrayOop inner_class_list = ikh()->inner_classes(); - guarantee(inner_class_list != NULL && inner_class_list->length() == length, + InnerClassesIterator iter(ikh()); + guarantee(iter.length() != 0 && iter.length() == length, "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; u4 size = 2 + entry_count * (2+2+2+2); write_attribute_name_index("InnerClasses"); write_u4(size); write_u2(entry_count); - for (int i = 0; i < length; i += instanceKlass::inner_class_next_offset) { - write_u2(inner_class_list_h->ushort_at( - i + instanceKlass::inner_class_inner_class_info_offset)); - write_u2(inner_class_list_h->ushort_at( - i + instanceKlass::inner_class_outer_class_info_offset)); - 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)); + for (; !iter.done(); iter.next()) { + write_u2(iter.inner_class_info_index()); + write_u2(iter.outer_class_info_index()); + write_u2(iter.inner_name_index()); + write_u2(iter.inner_access_flags()); } } diff -r bc8881f974b8 -r 0698f5ef5535 src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Mar 23 22:34:22 2012 -0700 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Sun Mar 25 18:08:52 2012 -0400 @@ -2400,44 +2400,33 @@ // new constant indices as needed. The inner classes info is a // quadruple: // (inner_class_info, outer_class_info, inner_name, inner_access_flags) - typeArrayOop inner_class_list = scratch_class->inner_classes(); - int icl_length = (inner_class_list == NULL) ? 0 : inner_class_list->length(); - if (icl_length > 0) { - typeArrayHandle inner_class_list_h(THREAD, inner_class_list); - for (int i = 0; i < icl_length; - i += instanceKlass::inner_class_next_offset) { - int cur_index = inner_class_list_h->ushort_at(i - + instanceKlass::inner_class_inner_class_info_offset); - if (cur_index == 0) { - continue; // JVM spec. allows null inner class refs so skip it - } - int new_index = find_new_index(cur_index); - if (new_index != 0) { - RC_TRACE_WITH_THREAD(0x00080000, THREAD, - ("inner_class_info change: %d to %d", cur_index, new_index)); - inner_class_list_h->ushort_at_put(i - + instanceKlass::inner_class_inner_class_info_offset, new_index); - } - cur_index = inner_class_list_h->ushort_at(i - + instanceKlass::inner_class_outer_class_info_offset); - new_index = find_new_index(cur_index); - if (new_index != 0) { - RC_TRACE_WITH_THREAD(0x00080000, THREAD, - ("outer_class_info change: %d to %d", cur_index, new_index)); - inner_class_list_h->ushort_at_put(i - + instanceKlass::inner_class_outer_class_info_offset, new_index); - } - 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 + InnerClassesIterator iter(scratch_class); + for (; !iter.done(); iter.next()) { + int cur_index = iter.inner_class_info_index(); + if (cur_index == 0) { + continue; // JVM spec. allows null inner class refs so skip it + } + int new_index = find_new_index(cur_index); + if (new_index != 0) { + RC_TRACE_WITH_THREAD(0x00080000, THREAD, + ("inner_class_info change: %d to %d", cur_index, new_index)); + iter.set_inner_class_info_index(new_index); + } + cur_index = iter.outer_class_info_index(); + new_index = find_new_index(cur_index); + if (new_index != 0) { + RC_TRACE_WITH_THREAD(0x00080000, THREAD, + ("outer_class_info change: %d to %d", cur_index, new_index)); + iter.set_outer_class_info_index(new_index); + } + cur_index = iter.inner_name_index(); + 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)); + iter.set_inner_name_index(new_index); + } + } // end for each inner class // Attach each method in klass to the new constant pool and update // to use new constant pool indices as needed: diff -r bc8881f974b8 -r 0698f5ef5535 src/share/vm/runtime/reflection.cpp --- a/src/share/vm/runtime/reflection.cpp Fri Mar 23 22:34:22 2012 -0700 +++ b/src/share/vm/runtime/reflection.cpp Sun Mar 25 18:08:52 2012 -0400 @@ -591,14 +591,11 @@ // Caller is responsible for figuring out in advance which case must be true. void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, bool inner_is_member, TRAPS) { - const int inner_class_info_index = 0; - const int outer_class_info_index = 1; - - typeArrayHandle icls (THREAD, outer->inner_classes()); + InnerClassesIterator iter(outer); constantPoolHandle cp (THREAD, outer->constants()); - for(int i = 0; i < icls->length(); i += 4) { - int ioff = icls->ushort_at(i + inner_class_info_index); - int ooff = icls->ushort_at(i + outer_class_info_index); + for (; !iter.done(); iter.next()) { + int ioff = iter.inner_class_info_index(); + int ooff = iter.outer_class_info_index(); if (inner_is_member && ioff != 0 && ooff != 0) { klassOop o = cp->klass_at(ooff, CHECK);