2313 |
2313 |
2314 // Inner classes can be static, private or protected (classic VM does this) |
2314 // Inner classes can be static, private or protected (classic VM does this) |
2315 #define RECOGNIZED_INNER_CLASS_MODIFIERS (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC) |
2315 #define RECOGNIZED_INNER_CLASS_MODIFIERS (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC) |
2316 |
2316 |
2317 // Return number of classes in the inner classes attribute table |
2317 // Return number of classes in the inner classes attribute table |
2318 u2 ClassFileParser::parse_classfile_inner_classes_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) { |
2318 u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start, |
|
2319 bool parsed_enclosingmethod_attribute, |
|
2320 u2 enclosing_method_class_index, |
|
2321 u2 enclosing_method_method_index, |
|
2322 constantPoolHandle cp, |
|
2323 instanceKlassHandle k, TRAPS) { |
2319 ClassFileStream* cfs = stream(); |
2324 ClassFileStream* cfs = stream(); |
2320 cfs->guarantee_more(2, CHECK_0); // length |
2325 u1* current_mark = cfs->current(); |
2321 u2 length = cfs->get_u2_fast(); |
2326 u2 length = 0; |
2322 |
2327 if (inner_classes_attribute_start != NULL) { |
2323 // 4-tuples of shorts [inner_class_info_index, outer_class_info_index, inner_name_index, inner_class_access_flags] |
2328 cfs->set_current(inner_classes_attribute_start); |
2324 typeArrayOop ic = oopFactory::new_permanent_shortArray(length*4, CHECK_0); |
2329 cfs->guarantee_more(2, CHECK_0); // length |
|
2330 length = cfs->get_u2_fast(); |
|
2331 } |
|
2332 |
|
2333 // 4-tuples of shorts of inner classes data and 2 shorts of enclosing |
|
2334 // method data: |
|
2335 // [inner_class_info_index, |
|
2336 // outer_class_info_index, |
|
2337 // inner_name_index, |
|
2338 // inner_class_access_flags, |
|
2339 // ... |
|
2340 // enclosing_method_class_index, |
|
2341 // enclosing_method_method_index] |
|
2342 int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0); |
|
2343 typeArrayOop ic = oopFactory::new_permanent_shortArray(size, CHECK_0); |
2325 typeArrayHandle inner_classes(THREAD, ic); |
2344 typeArrayHandle inner_classes(THREAD, ic); |
2326 int index = 0; |
2345 int index = 0; |
2327 int cp_size = cp->length(); |
2346 int cp_size = cp->length(); |
2328 cfs->guarantee_more(8 * length, CHECK_0); // 4-tuples of u2 |
2347 cfs->guarantee_more(8 * length, CHECK_0); // 4-tuples of u2 |
2329 for (int n = 0; n < length; n++) { |
2348 for (int n = 0; n < length; n++) { |
2370 inner_classes->short_at_put(index++, inner_access_flags.as_short()); |
2389 inner_classes->short_at_put(index++, inner_access_flags.as_short()); |
2371 } |
2390 } |
2372 |
2391 |
2373 // 4347400: make sure there's no duplicate entry in the classes array |
2392 // 4347400: make sure there's no duplicate entry in the classes array |
2374 if (_need_verify && _major_version >= JAVA_1_5_VERSION) { |
2393 if (_need_verify && _major_version >= JAVA_1_5_VERSION) { |
2375 for(int i = 0; i < inner_classes->length(); i += 4) { |
2394 for(int i = 0; i < length * 4; i += 4) { |
2376 for(int j = i + 4; j < inner_classes->length(); j += 4) { |
2395 for(int j = i + 4; j < length * 4; j += 4) { |
2377 guarantee_property((inner_classes->ushort_at(i) != inner_classes->ushort_at(j) || |
2396 guarantee_property((inner_classes->ushort_at(i) != inner_classes->ushort_at(j) || |
2378 inner_classes->ushort_at(i+1) != inner_classes->ushort_at(j+1) || |
2397 inner_classes->ushort_at(i+1) != inner_classes->ushort_at(j+1) || |
2379 inner_classes->ushort_at(i+2) != inner_classes->ushort_at(j+2) || |
2398 inner_classes->ushort_at(i+2) != inner_classes->ushort_at(j+2) || |
2380 inner_classes->ushort_at(i+3) != inner_classes->ushort_at(j+3)), |
2399 inner_classes->ushort_at(i+3) != inner_classes->ushort_at(j+3)), |
2381 "Duplicate entry in InnerClasses in class file %s", |
2400 "Duplicate entry in InnerClasses in class file %s", |
2382 CHECK_0); |
2401 CHECK_0); |
2383 } |
2402 } |
2384 } |
2403 } |
2385 } |
2404 } |
2386 |
2405 |
|
2406 // Set EnclosingMethod class and method indexes. |
|
2407 if (parsed_enclosingmethod_attribute) { |
|
2408 inner_classes->short_at_put(index++, enclosing_method_class_index); |
|
2409 inner_classes->short_at_put(index++, enclosing_method_method_index); |
|
2410 } |
|
2411 assert(index == size, "wrong size"); |
|
2412 |
2387 // Update instanceKlass with inner class info. |
2413 // Update instanceKlass with inner class info. |
2388 k->set_inner_classes(inner_classes()); |
2414 k->set_inner_classes(inner_classes()); |
|
2415 |
|
2416 // Restore buffer's current position. |
|
2417 cfs->set_current(current_mark); |
|
2418 |
2389 return length; |
2419 return length; |
2390 } |
2420 } |
2391 |
2421 |
2392 void ClassFileParser::parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) { |
2422 void ClassFileParser::parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) { |
2393 k->set_is_synthetic(); |
2423 k->set_is_synthetic(); |
2488 bool parsed_bootstrap_methods_attribute = false; |
2518 bool parsed_bootstrap_methods_attribute = false; |
2489 u1* runtime_visible_annotations = NULL; |
2519 u1* runtime_visible_annotations = NULL; |
2490 int runtime_visible_annotations_length = 0; |
2520 int runtime_visible_annotations_length = 0; |
2491 u1* runtime_invisible_annotations = NULL; |
2521 u1* runtime_invisible_annotations = NULL; |
2492 int runtime_invisible_annotations_length = 0; |
2522 int runtime_invisible_annotations_length = 0; |
|
2523 u1* inner_classes_attribute_start = NULL; |
|
2524 u4 inner_classes_attribute_length = 0; |
|
2525 u2 enclosing_method_class_index = 0; |
|
2526 u2 enclosing_method_method_index = 0; |
2493 // Iterate over attributes |
2527 // Iterate over attributes |
2494 while (attributes_count--) { |
2528 while (attributes_count--) { |
2495 cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length |
2529 cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length |
2496 u2 attribute_name_index = cfs->get_u2_fast(); |
2530 u2 attribute_name_index = cfs->get_u2_fast(); |
2497 u4 attribute_length = cfs->get_u4_fast(); |
2531 u4 attribute_length = cfs->get_u4_fast(); |
2520 if (parsed_innerclasses_attribute) { |
2554 if (parsed_innerclasses_attribute) { |
2521 classfile_parse_error("Multiple InnerClasses attributes in class file %s", CHECK); |
2555 classfile_parse_error("Multiple InnerClasses attributes in class file %s", CHECK); |
2522 } else { |
2556 } else { |
2523 parsed_innerclasses_attribute = true; |
2557 parsed_innerclasses_attribute = true; |
2524 } |
2558 } |
2525 u2 num_of_classes = parse_classfile_inner_classes_attribute(cp, k, CHECK); |
2559 inner_classes_attribute_start = cfs->get_u1_buffer(); |
2526 if (_need_verify && _major_version >= JAVA_1_5_VERSION) { |
2560 inner_classes_attribute_length = attribute_length; |
2527 guarantee_property(attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes, |
2561 cfs->skip_u1(inner_classes_attribute_length, CHECK); |
2528 "Wrong InnerClasses attribute length in class file %s", CHECK); |
|
2529 } |
|
2530 } else if (tag == vmSymbols::tag_synthetic()) { |
2562 } else if (tag == vmSymbols::tag_synthetic()) { |
2531 // Check for Synthetic tag |
2563 // Check for Synthetic tag |
2532 // Shouldn't we check that the synthetic flags wasn't already set? - not required in spec |
2564 // Shouldn't we check that the synthetic flags wasn't already set? - not required in spec |
2533 if (attribute_length != 0) { |
2565 if (attribute_length != 0) { |
2534 classfile_parse_error( |
2566 classfile_parse_error( |
2566 classfile_parse_error("Multiple EnclosingMethod attributes in class file %s", CHECK); |
2598 classfile_parse_error("Multiple EnclosingMethod attributes in class file %s", CHECK); |
2567 } else { |
2599 } else { |
2568 parsed_enclosingmethod_attribute = true; |
2600 parsed_enclosingmethod_attribute = true; |
2569 } |
2601 } |
2570 cfs->guarantee_more(4, CHECK); // class_index, method_index |
2602 cfs->guarantee_more(4, CHECK); // class_index, method_index |
2571 u2 class_index = cfs->get_u2_fast(); |
2603 enclosing_method_class_index = cfs->get_u2_fast(); |
2572 u2 method_index = cfs->get_u2_fast(); |
2604 enclosing_method_method_index = cfs->get_u2_fast(); |
2573 if (class_index == 0) { |
2605 if (enclosing_method_class_index == 0) { |
2574 classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", CHECK); |
2606 classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", CHECK); |
2575 } |
2607 } |
2576 // Validate the constant pool indices and types |
2608 // Validate the constant pool indices and types |
2577 if (!cp->is_within_bounds(class_index) || |
2609 if (!cp->is_within_bounds(enclosing_method_class_index) || |
2578 !is_klass_reference(cp, class_index)) { |
2610 !is_klass_reference(cp, enclosing_method_class_index)) { |
2579 classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK); |
2611 classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK); |
2580 } |
2612 } |
2581 if (method_index != 0 && |
2613 if (enclosing_method_method_index != 0 && |
2582 (!cp->is_within_bounds(method_index) || |
2614 (!cp->is_within_bounds(enclosing_method_method_index) || |
2583 !cp->tag_at(method_index).is_name_and_type())) { |
2615 !cp->tag_at(enclosing_method_method_index).is_name_and_type())) { |
2584 classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK); |
2616 classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK); |
2585 } |
2617 } |
2586 k->set_enclosing_method_indices(class_index, method_index); |
|
2587 } else if (tag == vmSymbols::tag_bootstrap_methods() && |
2618 } else if (tag == vmSymbols::tag_bootstrap_methods() && |
2588 _major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { |
2619 _major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { |
2589 if (parsed_bootstrap_methods_attribute) |
2620 if (parsed_bootstrap_methods_attribute) |
2590 classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK); |
2621 classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK); |
2591 parsed_bootstrap_methods_attribute = true; |
2622 parsed_bootstrap_methods_attribute = true; |
2603 runtime_visible_annotations_length, |
2634 runtime_visible_annotations_length, |
2604 runtime_invisible_annotations, |
2635 runtime_invisible_annotations, |
2605 runtime_invisible_annotations_length, |
2636 runtime_invisible_annotations_length, |
2606 CHECK); |
2637 CHECK); |
2607 k->set_class_annotations(annotations()); |
2638 k->set_class_annotations(annotations()); |
|
2639 |
|
2640 if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) { |
|
2641 u2 num_of_classes = parse_classfile_inner_classes_attribute( |
|
2642 inner_classes_attribute_start, |
|
2643 parsed_innerclasses_attribute, |
|
2644 enclosing_method_class_index, |
|
2645 enclosing_method_method_index, |
|
2646 cp, k, CHECK); |
|
2647 if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) { |
|
2648 guarantee_property( |
|
2649 inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes, |
|
2650 "Wrong InnerClasses attribute length in class file %s", CHECK); |
|
2651 } |
|
2652 } |
2608 |
2653 |
2609 if (_max_bootstrap_specifier_index >= 0) { |
2654 if (_max_bootstrap_specifier_index >= 0) { |
2610 guarantee_property(parsed_bootstrap_methods_attribute, |
2655 guarantee_property(parsed_bootstrap_methods_attribute, |
2611 "Missing BootstrapMethods attribute in class file %s", CHECK); |
2656 "Missing BootstrapMethods attribute in class file %s", CHECK); |
2612 } |
2657 } |