diff -r 56e3093129dc -r 6a9cfc59a18a hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Mar 09 13:34:45 2012 -0800 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Tue Mar 13 13:50:48 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);