diff --git a/make/bsd/makefiles/mapfile-vers-debug b/make/bsd/makefiles/mapfile-vers-debug index 9a2d42fb695766c6870076cefb5cd2b472132e2b..52e8f435665499ae77c3c0e0cf211768c31b56bc 100644 --- a/make/bsd/makefiles/mapfile-vers-debug +++ b/make/bsd/makefiles/mapfile-vers-debug @@ -126,8 +126,9 @@ SUNWprivate_1.1 { JVM_GetClassModifiers; JVM_GetClassName; JVM_GetClassNameUTF; - JVM_GetClassSignature; + JVM_GetClassSignature; JVM_GetClassSigners; + JVM_GetClassTypeAnnotations; JVM_GetComponentType; JVM_GetDeclaredClasses; JVM_GetDeclaringClass; diff --git a/make/bsd/makefiles/mapfile-vers-product b/make/bsd/makefiles/mapfile-vers-product index 7a5d7c7dfe2eabf0c25f63247014a6ffb1310a29..05e9a44a1fc98c80a13e0a3ca5df38524495b304 100644 --- a/make/bsd/makefiles/mapfile-vers-product +++ b/make/bsd/makefiles/mapfile-vers-product @@ -128,6 +128,7 @@ SUNWprivate_1.1 { JVM_GetClassNameUTF; JVM_GetClassSignature; JVM_GetClassSigners; + JVM_GetClassTypeAnnotations; JVM_GetComponentType; JVM_GetDeclaredClasses; JVM_GetDeclaringClass; diff --git a/make/linux/makefiles/mapfile-vers-debug b/make/linux/makefiles/mapfile-vers-debug index 1a0bc01a626dd2c7c3cd9689133dc44cf0e49817..93ddc5666a03e3f6f7a72411e7b2109eaac4831e 100644 --- a/make/linux/makefiles/mapfile-vers-debug +++ b/make/linux/makefiles/mapfile-vers-debug @@ -124,6 +124,7 @@ SUNWprivate_1.1 { JVM_GetClassNameUTF; JVM_GetClassSignature; JVM_GetClassSigners; + JVM_GetClassTypeAnnotations; JVM_GetComponentType; JVM_GetDeclaredClasses; JVM_GetDeclaringClass; diff --git a/make/linux/makefiles/mapfile-vers-product b/make/linux/makefiles/mapfile-vers-product index e53bc5c0d8fc35a43b40a68567766182cb30ae8d..029c12c5ff92fcee76bf137a6c4e7ca2a3c117e3 100644 --- a/make/linux/makefiles/mapfile-vers-product +++ b/make/linux/makefiles/mapfile-vers-product @@ -124,6 +124,7 @@ SUNWprivate_1.1 { JVM_GetClassNameUTF; JVM_GetClassSignature; JVM_GetClassSigners; + JVM_GetClassTypeAnnotations; JVM_GetComponentType; JVM_GetDeclaredClasses; JVM_GetDeclaringClass; diff --git a/make/solaris/makefiles/mapfile-vers b/make/solaris/makefiles/mapfile-vers index eb5554858eb9e99127073cebc9cdaa5e4b8a4910..76af87c0ce510bcff8e1fb6c8b0cb17d9a43a396 100644 --- a/make/solaris/makefiles/mapfile-vers +++ b/make/solaris/makefiles/mapfile-vers @@ -125,6 +125,7 @@ SUNWprivate_1.1 { JVM_GetClassSignature; JVM_GetClassSigners; JVM_GetComponentType; + JVM_GetClassTypeAnnotations; JVM_GetDeclaredClasses; JVM_GetDeclaringClass; JVM_GetEnclosingMethodInfo; diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp index a13bdab006d231e45e76ddda975153fb50ef4b6c..956acea7a257daf5417c26e241f161179ef1c14d 100644 --- a/src/share/vm/classfile/classFileParser.cpp +++ b/src/share/vm/classfile/classFileParser.cpp @@ -906,6 +906,7 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data, bool* is_synthetic_addr, u2* generic_signature_index_addr, AnnotationArray** field_annotations, + AnnotationArray** field_type_annotations, ClassFileParser::FieldAnnotationCollector* parsed_annotations, TRAPS) { ClassFileStream* cfs = stream(); @@ -917,6 +918,10 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data, int runtime_visible_annotations_length = 0; u1* runtime_invisible_annotations = NULL; int runtime_invisible_annotations_length = 0; + u1* runtime_visible_type_annotations = NULL; + int runtime_visible_type_annotations_length = 0; + u1* runtime_invisible_type_annotations = NULL; + int runtime_invisible_type_annotations_length = 0; while (attributes_count--) { cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length u2 attribute_name_index = cfs->get_u2_fast(); @@ -971,6 +976,16 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data, runtime_invisible_annotations = cfs->get_u1_buffer(); assert(runtime_invisible_annotations != NULL, "null invisible annotations"); cfs->skip_u1(runtime_invisible_annotations_length, CHECK); + } else if (attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { + runtime_visible_type_annotations_length = attribute_length; + runtime_visible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_visible_type_annotations != NULL, "null visible type annotations"); + cfs->skip_u1(runtime_visible_type_annotations_length, CHECK); + } else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { + runtime_invisible_type_annotations_length = attribute_length; + runtime_invisible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations"); + cfs->skip_u1(runtime_invisible_type_annotations_length, CHECK); } else { cfs->skip_u1(attribute_length, CHECK); // Skip unknown attributes } @@ -988,6 +1003,12 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data, runtime_invisible_annotations, runtime_invisible_annotations_length, CHECK); + *field_type_annotations = assemble_annotations(loader_data, + runtime_visible_type_annotations, + runtime_visible_type_annotations_length, + runtime_invisible_type_annotations, + runtime_invisible_type_annotations_length, + CHECK); return; } @@ -1084,6 +1105,7 @@ Array* ClassFileParser::parse_fields(ClassLoaderData* loader_data, bool is_interface, FieldAllocationCount *fac, Array** fields_annotations, + Array** fields_type_annotations, u2* java_fields_count_ptr, TRAPS) { ClassFileStream* cfs = stream(); cfs->guarantee_more(2, CHECK_NULL); // length @@ -1119,6 +1141,7 @@ Array* ClassFileParser::parse_fields(ClassLoaderData* loader_data, THREAD, u2, total_fields * (FieldInfo::field_slots + 1)); AnnotationArray* field_annotations = NULL; + AnnotationArray* field_type_annotations = NULL; // The generic signature slots start after all other fields' data. int generic_signature_slot = total_fields * FieldInfo::field_slots; int num_generic_signature = 0; @@ -1160,7 +1183,7 @@ Array* ClassFileParser::parse_fields(ClassLoaderData* loader_data, cp, attributes_count, is_static, signature_index, &constantvalue_index, &is_synthetic, &generic_signature_index, &field_annotations, - &parsed_annotations, + &field_type_annotations, &parsed_annotations, CHECK_NULL); if (field_annotations != NULL) { if (*fields_annotations == NULL) { @@ -1170,6 +1193,14 @@ Array* ClassFileParser::parse_fields(ClassLoaderData* loader_data, } (*fields_annotations)->at_put(n, field_annotations); } + if (field_type_annotations != NULL) { + if (*fields_type_annotations == NULL) { + *fields_type_annotations = MetadataFactory::new_array( + loader_data, length, NULL, + CHECK_NULL); + } + (*fields_type_annotations)->at_put(n, field_type_annotations); + } if (is_synthetic) { access_flags.set_is_synthetic(); } @@ -1831,6 +1862,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, AnnotationArray** method_annotations, AnnotationArray** method_parameter_annotations, AnnotationArray** method_default_annotations, + AnnotationArray** method_type_annotations, TRAPS) { ClassFileStream* cfs = stream(); methodHandle nullHandle; @@ -1918,6 +1950,10 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, int runtime_visible_parameter_annotations_length = 0; u1* runtime_invisible_parameter_annotations = NULL; int runtime_invisible_parameter_annotations_length = 0; + u1* runtime_visible_type_annotations = NULL; + int runtime_visible_type_annotations_length = 0; + u1* runtime_invisible_type_annotations = NULL; + int runtime_invisible_type_annotations_length = 0; u1* annotation_default = NULL; int annotation_default_length = 0; @@ -2159,6 +2195,17 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, annotation_default = cfs->get_u1_buffer(); assert(annotation_default != NULL, "null annotation default"); cfs->skip_u1(annotation_default_length, CHECK_(nullHandle)); + } else if (method_attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { + runtime_visible_type_annotations_length = method_attribute_length; + runtime_visible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_visible_type_annotations != NULL, "null visible type annotations"); + // No need for the VM to parse Type annotations + cfs->skip_u1(runtime_visible_type_annotations_length, CHECK_(nullHandle)); + } else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { + runtime_invisible_type_annotations_length = method_attribute_length; + runtime_invisible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations"); + cfs->skip_u1(runtime_invisible_type_annotations_length, CHECK_(nullHandle)); } else { // Skip unknown attributes cfs->skip_u1(method_attribute_length, CHECK_(nullHandle)); @@ -2333,6 +2380,12 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, NULL, 0, CHECK_(nullHandle)); + *method_type_annotations = assemble_annotations(loader_data, + runtime_visible_type_annotations, + runtime_visible_type_annotations_length, + runtime_invisible_type_annotations, + runtime_invisible_type_annotations_length, + CHECK_(nullHandle)); if (name == vmSymbols::finalize_method_name() && signature == vmSymbols::void_method_signature()) { @@ -2364,12 +2417,14 @@ Array* ClassFileParser::parse_methods(ClassLoaderData* loader_data, Array** methods_annotations, Array** methods_parameter_annotations, Array** methods_default_annotations, + Array** methods_type_annotations, bool* has_default_methods, TRAPS) { ClassFileStream* cfs = stream(); AnnotationArray* method_annotations = NULL; AnnotationArray* method_parameter_annotations = NULL; AnnotationArray* method_default_annotations = NULL; + AnnotationArray* method_type_annotations = NULL; cfs->guarantee_more(2, CHECK_NULL); // length u2 length = cfs->get_u2_fast(); if (length == 0) { @@ -2386,6 +2441,7 @@ Array* ClassFileParser::parse_methods(ClassLoaderData* loader_data, &method_annotations, &method_parameter_annotations, &method_default_annotations, + &method_type_annotations, CHECK_NULL); if (method->is_final()) { @@ -2411,7 +2467,13 @@ Array* ClassFileParser::parse_methods(ClassLoaderData* loader_data, MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); } (*methods_default_annotations)->at_put(index, method_default_annotations); + if (*methods_type_annotations == NULL) { + *methods_type_annotations = + MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); + } + (*methods_type_annotations)->at_put(index, method_type_annotations); } + if (_need_verify && length > 1) { // Check duplicated methods ResourceMark rm(THREAD); @@ -2445,6 +2507,7 @@ Array* ClassFileParser::sort_methods(ClassLoaderData* loader_data, Array* methods_annotations, Array* methods_parameter_annotations, Array* methods_default_annotations, + Array* methods_type_annotations, TRAPS) { int length = methods->length(); // If JVMTI original method ordering or sharing is enabled we have to @@ -2463,7 +2526,8 @@ Array* ClassFileParser::sort_methods(ClassLoaderData* loader_data, // Note that the ordering is not alphabetical, see Symbol::fast_compare Method::sort_methods(methods, methods_annotations, methods_parameter_annotations, - methods_default_annotations); + methods_default_annotations, + methods_type_annotations); // If JVMTI original method ordering or sharing is enabled construct int // array remembering the original ordering @@ -2728,6 +2792,10 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, int runtime_visible_annotations_length = 0; u1* runtime_invisible_annotations = NULL; int runtime_invisible_annotations_length = 0; + u1* runtime_visible_type_annotations = NULL; + int runtime_visible_type_annotations_length = 0; + u1* runtime_invisible_type_annotations = NULL; + int runtime_invisible_type_annotations_length = 0; u1* inner_classes_attribute_start = NULL; u4 inner_classes_attribute_length = 0; u2 enclosing_method_class_index = 0; @@ -2834,6 +2902,17 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK); parsed_bootstrap_methods_attribute = true; parse_classfile_bootstrap_methods_attribute(loader_data, cp, attribute_length, CHECK); + } else if (tag == vmSymbols::tag_runtime_visible_type_annotations()) { + runtime_visible_type_annotations_length = attribute_length; + runtime_visible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_visible_type_annotations != NULL, "null visible type annotations"); + // No need for the VM to parse Type annotations + cfs->skip_u1(runtime_visible_type_annotations_length, CHECK); + } else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_type_annotations()) { + runtime_invisible_type_annotations_length = attribute_length; + runtime_invisible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations"); + cfs->skip_u1(runtime_invisible_type_annotations_length, CHECK); } else { // Unknown attribute cfs->skip_u1(attribute_length, CHECK); @@ -2850,6 +2929,13 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data, runtime_invisible_annotations_length, CHECK); set_class_annotations(annotations); + AnnotationArray* type_annotations = assemble_annotations(loader_data, + runtime_visible_type_annotations, + runtime_visible_type_annotations_length, + runtime_invisible_type_annotations, + runtime_invisible_type_annotations_length, + CHECK); + set_class_type_annotations(type_annotations); if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) { u2 num_of_classes = parse_classfile_inner_classes_attribute( @@ -3190,7 +3276,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, // Fields (offsets are filled in later) FieldAllocationCount fac; Array* fields_annotations = NULL; + Array* fields_type_annotations = NULL; Array* fields = parse_fields(loader_data, class_name, cp, access_flags.is_interface(), &fac, &fields_annotations, + &fields_type_annotations, &java_fields_count, CHECK_(nullHandle)); // Methods @@ -3202,6 +3290,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, Array* methods_annotations = NULL; Array* methods_parameter_annotations = NULL; Array* methods_default_annotations = NULL; + Array* methods_type_annotations = NULL; Array* methods = parse_methods(loader_data, cp, access_flags.is_interface(), &promoted_flags, @@ -3209,6 +3298,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, &methods_annotations, &methods_parameter_annotations, &methods_default_annotations, + &methods_type_annotations, &has_default_methods, CHECK_(nullHandle)); @@ -3270,6 +3360,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, methods_annotations, methods_parameter_annotations, methods_default_annotations, + methods_type_annotations, CHECK_(nullHandle)); // promote flags from parse_methods() to the klass' flags @@ -3687,11 +3778,13 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, if (is_anonymous()) // I am well known to myself cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve + // Allocate an annotation type if needed. if (fields_annotations != NULL || methods_annotations != NULL || methods_parameter_annotations != NULL || - methods_default_annotations != NULL) { - // Allocate an annotation type if needed. + methods_default_annotations != NULL || + fields_type_annotations != NULL || + methods_type_annotations != NULL) { Annotations* anno = Annotations::allocate(loader_data, fields_annotations, methods_annotations, methods_parameter_annotations, @@ -3701,6 +3794,16 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, this_klass->set_annotations(NULL); } + if (fields_type_annotations != NULL || + methods_type_annotations != NULL) { + assert(this_klass->annotations() != NULL, "annotations should have been allocated"); + Annotations* anno = Annotations::allocate(loader_data, + fields_type_annotations, + methods_type_annotations, + NULL, + NULL, CHECK_(nullHandle)); + this_klass->annotations()->set_type_annotations(anno); + } this_klass->set_minor_version(minor_version); this_klass->set_major_version(major_version); @@ -3725,6 +3828,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, // Fill in field values obtained by parse_classfile_attributes if (parsed_annotations.has_any_annotations()) parsed_annotations.apply_to(this_klass); + // Create annotations if (_annotations != NULL && this_klass->annotations() == NULL) { Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL); @@ -3732,6 +3836,19 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, } apply_parsed_class_attributes(this_klass); + // Create type annotations + if (_type_annotations != NULL) { + if (this_klass->annotations() == NULL) { + Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL); + this_klass->set_annotations(anno); + } + if (this_klass->annotations()->type_annotations() == NULL) { + Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL); + this_klass->annotations()->set_type_annotations(anno); + } + this_klass->annotations()->type_annotations()->set_class_annotations(_type_annotations); + } + // Miranda methods if ((num_miranda_methods > 0) || // if this class introduced new miranda methods or diff --git a/src/share/vm/classfile/classFileParser.hpp b/src/share/vm/classfile/classFileParser.hpp index c5b4701838a1676b14ec92835f8944f4e15bb7ba..5a5d3fc397a5aceb3fb8cefc4779b8f4d70ba3df 100644 --- a/src/share/vm/classfile/classFileParser.hpp +++ b/src/share/vm/classfile/classFileParser.hpp @@ -64,6 +64,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { int _sde_length; Array* _inner_classes; AnnotationArray* _annotations; + AnnotationArray* _type_annotations; void set_class_synthetic_flag(bool x) { _synthetic_flag = x; } void set_class_sourcefile(Symbol* x) { _sourcefile = x; } @@ -71,12 +72,14 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { void set_class_sde_buffer(char* x, int len) { _sde_buffer = x; _sde_length = len; } void set_class_inner_classes(Array* x) { _inner_classes = x; } void set_class_annotations(AnnotationArray* x) { _annotations = x; } + void set_class_type_annotations(AnnotationArray* x) { _type_annotations = x; } void init_parsed_class_attributes() { _synthetic_flag = false; _sourcefile = NULL; _generic_signature = NULL; _sde_buffer = NULL; _sde_length = 0; + _annotations = _type_annotations = NULL; // initialize the other flags too: _has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false; _max_bootstrap_specifier_index = -1; @@ -163,6 +166,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { bool* is_synthetic_addr, u2* generic_signature_index_addr, AnnotationArray** field_annotations, + AnnotationArray** field_type_annotations, FieldAnnotationCollector* parsed_annotations, TRAPS); Array* parse_fields(ClassLoaderData* loader_data, @@ -170,6 +174,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { constantPoolHandle cp, bool is_interface, FieldAllocationCount *fac, Array** fields_annotations, + Array** fields_type_annotations, u2* java_fields_count_ptr, TRAPS); // Method parsing @@ -180,6 +185,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { AnnotationArray** method_annotations, AnnotationArray** method_parameter_annotations, AnnotationArray** method_default_annotations, + AnnotationArray** method_type_annotations, TRAPS); Array* parse_methods(ClassLoaderData* loader_data, constantPoolHandle cp, @@ -189,6 +195,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { Array** methods_annotations, Array** methods_parameter_annotations, Array** methods_default_annotations, + Array** methods_type_annotations, bool* has_default_method, TRAPS); Array* sort_methods(ClassLoaderData* loader_data, @@ -196,6 +203,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { Array* methods_annotations, Array* methods_parameter_annotations, Array* methods_default_annotations, + Array* methods_type_annotations, TRAPS); u2* parse_exception_table(ClassLoaderData* loader_data, u4 code_length, u4 exception_table_length, diff --git a/src/share/vm/classfile/javaClasses.cpp b/src/share/vm/classfile/javaClasses.cpp index 80b15fbd2d145f136bf9417473e8003f5e433c27..79a35008575e8274e04dbcc6e647912bd2b6dc32 100644 --- a/src/share/vm/classfile/javaClasses.cpp +++ b/src/share/vm/classfile/javaClasses.cpp @@ -1813,10 +1813,12 @@ void java_lang_reflect_Method::compute_offsets() { annotations_offset = -1; parameter_annotations_offset = -1; annotation_default_offset = -1; + type_annotations_offset = -1; compute_optional_offset(signature_offset, k, vmSymbols::signature_name(), vmSymbols::string_signature()); compute_optional_offset(annotations_offset, k, vmSymbols::annotations_name(), vmSymbols::byte_array_signature()); compute_optional_offset(parameter_annotations_offset, k, vmSymbols::parameter_annotations_name(), vmSymbols::byte_array_signature()); compute_optional_offset(annotation_default_offset, k, vmSymbols::annotation_default_name(), vmSymbols::byte_array_signature()); + compute_optional_offset(type_annotations_offset, k, vmSymbols::type_annotations_name(), vmSymbols::byte_array_signature()); } Handle java_lang_reflect_Method::create(TRAPS) { @@ -1962,6 +1964,22 @@ void java_lang_reflect_Method::set_annotation_default(oop method, oop value) { method->obj_field_put(annotation_default_offset, value); } +bool java_lang_reflect_Method::has_type_annotations_field() { + return (type_annotations_offset >= 0); +} + +oop java_lang_reflect_Method::type_annotations(oop method) { + assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); + assert(has_type_annotations_field(), "type_annotations field must be present"); + return method->obj_field(type_annotations_offset); +} + +void java_lang_reflect_Method::set_type_annotations(oop method, oop value) { + assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); + assert(has_type_annotations_field(), "type_annotations field must be present"); + method->obj_field_put(type_annotations_offset, value); +} + void java_lang_reflect_Constructor::compute_offsets() { Klass* k = SystemDictionary::reflect_Constructor_klass(); compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); @@ -1973,9 +1991,11 @@ void java_lang_reflect_Constructor::compute_offsets() { signature_offset = -1; annotations_offset = -1; parameter_annotations_offset = -1; + type_annotations_offset = -1; compute_optional_offset(signature_offset, k, vmSymbols::signature_name(), vmSymbols::string_signature()); compute_optional_offset(annotations_offset, k, vmSymbols::annotations_name(), vmSymbols::byte_array_signature()); compute_optional_offset(parameter_annotations_offset, k, vmSymbols::parameter_annotations_name(), vmSymbols::byte_array_signature()); + compute_optional_offset(type_annotations_offset, k, vmSymbols::type_annotations_name(), vmSymbols::byte_array_signature()); } Handle java_lang_reflect_Constructor::create(TRAPS) { @@ -2086,6 +2106,22 @@ void java_lang_reflect_Constructor::set_parameter_annotations(oop method, oop va method->obj_field_put(parameter_annotations_offset, value); } +bool java_lang_reflect_Constructor::has_type_annotations_field() { + return (type_annotations_offset >= 0); +} + +oop java_lang_reflect_Constructor::type_annotations(oop constructor) { + assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); + assert(has_type_annotations_field(), "type_annotations field must be present"); + return constructor->obj_field(type_annotations_offset); +} + +void java_lang_reflect_Constructor::set_type_annotations(oop constructor, oop value) { + assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); + assert(has_type_annotations_field(), "type_annotations field must be present"); + constructor->obj_field_put(type_annotations_offset, value); +} + void java_lang_reflect_Field::compute_offsets() { Klass* k = SystemDictionary::reflect_Field_klass(); compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); @@ -2096,8 +2132,10 @@ void java_lang_reflect_Field::compute_offsets() { // The generic signature and annotations fields are only present in 1.5 signature_offset = -1; annotations_offset = -1; + type_annotations_offset = -1; compute_optional_offset(signature_offset, k, vmSymbols::signature_name(), vmSymbols::string_signature()); compute_optional_offset(annotations_offset, k, vmSymbols::annotations_name(), vmSymbols::byte_array_signature()); + compute_optional_offset(type_annotations_offset, k, vmSymbols::type_annotations_name(), vmSymbols::byte_array_signature()); } Handle java_lang_reflect_Field::create(TRAPS) { @@ -2192,6 +2230,21 @@ void java_lang_reflect_Field::set_annotations(oop field, oop value) { field->obj_field_put(annotations_offset, value); } +bool java_lang_reflect_Field::has_type_annotations_field() { + return (type_annotations_offset >= 0); +} + +oop java_lang_reflect_Field::type_annotations(oop field) { + assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); + assert(has_type_annotations_field(), "type_annotations field must be present"); + return field->obj_field(type_annotations_offset); +} + +void java_lang_reflect_Field::set_type_annotations(oop field, oop value) { + assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); + assert(has_type_annotations_field(), "type_annotations field must be present"); + field->obj_field_put(type_annotations_offset, value); +} void sun_reflect_ConstantPool::compute_offsets() { Klass* k = SystemDictionary::reflect_ConstantPool_klass(); @@ -2857,6 +2910,7 @@ int java_lang_reflect_Method::signature_offset; int java_lang_reflect_Method::annotations_offset; int java_lang_reflect_Method::parameter_annotations_offset; int java_lang_reflect_Method::annotation_default_offset; +int java_lang_reflect_Method::type_annotations_offset; int java_lang_reflect_Constructor::clazz_offset; int java_lang_reflect_Constructor::parameterTypes_offset; int java_lang_reflect_Constructor::exceptionTypes_offset; @@ -2865,6 +2919,7 @@ int java_lang_reflect_Constructor::modifiers_offset; int java_lang_reflect_Constructor::signature_offset; int java_lang_reflect_Constructor::annotations_offset; int java_lang_reflect_Constructor::parameter_annotations_offset; +int java_lang_reflect_Constructor::type_annotations_offset; int java_lang_reflect_Field::clazz_offset; int java_lang_reflect_Field::name_offset; int java_lang_reflect_Field::type_offset; @@ -2872,6 +2927,7 @@ int java_lang_reflect_Field::slot_offset; int java_lang_reflect_Field::modifiers_offset; int java_lang_reflect_Field::signature_offset; int java_lang_reflect_Field::annotations_offset; +int java_lang_reflect_Field::type_annotations_offset; int java_lang_boxing_object::value_offset; int java_lang_boxing_object::long_value_offset; int java_lang_ref_Reference::referent_offset; diff --git a/src/share/vm/classfile/javaClasses.hpp b/src/share/vm/classfile/javaClasses.hpp index 9359d5b3c6eb02d920e2b04a0a5181e0889f553a..1a4b51f59978d948be975d4286bd91c84c329ff0 100644 --- a/src/share/vm/classfile/javaClasses.hpp +++ b/src/share/vm/classfile/javaClasses.hpp @@ -554,6 +554,7 @@ class java_lang_reflect_Method : public java_lang_reflect_AccessibleObject { static int annotations_offset; static int parameter_annotations_offset; static int annotation_default_offset; + static int type_annotations_offset; static void compute_offsets(); @@ -599,6 +600,10 @@ class java_lang_reflect_Method : public java_lang_reflect_AccessibleObject { static oop annotation_default(oop method); static void set_annotation_default(oop method, oop value); + static bool has_type_annotations_field(); + static oop type_annotations(oop method); + static void set_type_annotations(oop method, oop value); + // Debugging friend class JavaClasses; }; @@ -618,6 +623,7 @@ class java_lang_reflect_Constructor : public java_lang_reflect_AccessibleObject static int signature_offset; static int annotations_offset; static int parameter_annotations_offset; + static int type_annotations_offset; static void compute_offsets(); @@ -653,6 +659,10 @@ class java_lang_reflect_Constructor : public java_lang_reflect_AccessibleObject static oop parameter_annotations(oop method); static void set_parameter_annotations(oop method, oop value); + static bool has_type_annotations_field(); + static oop type_annotations(oop constructor); + static void set_type_annotations(oop constructor, oop value); + // Debugging friend class JavaClasses; }; @@ -671,6 +681,7 @@ class java_lang_reflect_Field : public java_lang_reflect_AccessibleObject { static int modifiers_offset; static int signature_offset; static int annotations_offset; + static int type_annotations_offset; static void compute_offsets(); @@ -710,6 +721,10 @@ class java_lang_reflect_Field : public java_lang_reflect_AccessibleObject { static oop annotation_default(oop method); static void set_annotation_default(oop method, oop value); + static bool has_type_annotations_field(); + static oop type_annotations(oop field); + static void set_type_annotations(oop field, oop value); + // Debugging friend class JavaClasses; }; diff --git a/src/share/vm/classfile/vmSymbols.hpp b/src/share/vm/classfile/vmSymbols.hpp index 940aac3c29b2bb3a226d37d0d7ed8e132f887594..5c9b6327eaaa5b24f638abb369dab6d36bacf049 100644 --- a/src/share/vm/classfile/vmSymbols.hpp +++ b/src/share/vm/classfile/vmSymbols.hpp @@ -136,6 +136,8 @@ template(tag_runtime_visible_parameter_annotations, "RuntimeVisibleParameterAnnotations") \ template(tag_runtime_invisible_parameter_annotations,"RuntimeInvisibleParameterAnnotations") \ template(tag_annotation_default, "AnnotationDefault") \ + template(tag_runtime_visible_type_annotations, "RuntimeVisibleTypeAnnotations") \ + template(tag_runtime_invisible_type_annotations, "RuntimeInvisibleTypeAnnotations") \ template(tag_enclosing_method, "EnclosingMethod") \ template(tag_bootstrap_methods, "BootstrapMethods") \ \ @@ -239,6 +241,9 @@ template(ConstantPool_name, "constantPoolOop") \ template(sun_reflect_UnsafeStaticFieldAccessorImpl, "sun/reflect/UnsafeStaticFieldAccessorImpl")\ template(base_name, "base") \ + /* Type Annotations (JDK 8 and above) */ \ + template(type_annotations_name, "typeAnnotations") \ + \ \ /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \ template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \ diff --git a/src/share/vm/oops/annotations.cpp b/src/share/vm/oops/annotations.cpp index 05ded22035b1c3c3cb18e4c754894a0d83e84791..72c5737f056de30aee9de49269206fe3435ec20b 100644 --- a/src/share/vm/oops/annotations.cpp +++ b/src/share/vm/oops/annotations.cpp @@ -61,6 +61,9 @@ void Annotations::deallocate_contents(ClassLoaderData* loader_data) { free_contents(loader_data, methods_annotations()); free_contents(loader_data, methods_parameter_annotations()); free_contents(loader_data, methods_default_annotations()); + + // Recursively deallocate optional Annotations linked through this one + MetadataFactory::free_metadata(loader_data, type_annotations()); } // Set the annotation at 'idnum' to 'anno'. diff --git a/src/share/vm/oops/annotations.hpp b/src/share/vm/oops/annotations.hpp index 63a42bbda56e1f9196248b7d20bfb393ee2e0120..07d05467ba1867ec8690ac3b598c68d1eb611aae 100644 --- a/src/share/vm/oops/annotations.hpp +++ b/src/share/vm/oops/annotations.hpp @@ -38,7 +38,8 @@ class outputStream; typedef Array AnnotationArray; // Class to hold the various types of annotations. The only metadata that points -// to this is InstanceKlass. +// to this is InstanceKlass, or another Annotations instance if this is a +// a type_annotation instance. class Annotations: public MetaspaceObj { @@ -58,6 +59,8 @@ class Annotations: public MetaspaceObj { // such annotations. // Index is the idnum, which is initially the same as the methods array index. Array* _methods_default_annotations; + // Type annotations for this class, or null if none. + Annotations* _type_annotations; // Constructor where some some values are known to not be null Annotations(Array* fa, Array* ma, @@ -66,7 +69,8 @@ class Annotations: public MetaspaceObj { _fields_annotations(fa), _methods_annotations(ma), _methods_parameter_annotations(mpa), - _methods_default_annotations(mda) {} + _methods_default_annotations(mda), + _type_annotations(NULL) {} public: // Allocate instance of this class @@ -81,22 +85,26 @@ class Annotations: public MetaspaceObj { static int size() { return sizeof(Annotations) / wordSize; } // Constructor to initialize to null - Annotations() : _class_annotations(NULL), _fields_annotations(NULL), + Annotations() : _class_annotations(NULL), + _fields_annotations(NULL), _methods_annotations(NULL), _methods_parameter_annotations(NULL), - _methods_default_annotations(NULL) {} + _methods_default_annotations(NULL), + _type_annotations(NULL) {} AnnotationArray* class_annotations() const { return _class_annotations; } Array* fields_annotations() const { return _fields_annotations; } Array* methods_annotations() const { return _methods_annotations; } Array* methods_parameter_annotations() const { return _methods_parameter_annotations; } Array* methods_default_annotations() const { return _methods_default_annotations; } + Annotations* type_annotations() const { return _type_annotations; } void set_class_annotations(AnnotationArray* md) { _class_annotations = md; } void set_fields_annotations(Array* md) { _fields_annotations = md; } void set_methods_annotations(Array* md) { _methods_annotations = md; } void set_methods_parameter_annotations(Array* md) { _methods_parameter_annotations = md; } void set_methods_default_annotations(Array* md) { _methods_default_annotations = md; } + void set_type_annotations(Annotations* annos) { _type_annotations = annos; } // Redefine classes support AnnotationArray* get_method_annotations_of(int idnum) @@ -129,6 +137,7 @@ class Annotations: public MetaspaceObj { inline AnnotationArray* get_method_annotations_from(int idnum, Array* annos); void set_annotations(Array* md, Array** md_p) { *md_p = md; } + bool is_klass() const { return false; } private: void set_methods_annotations_of(instanceKlassHandle ik, int idnum, AnnotationArray* anno, diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp index 69d1910f2b188a143c34714deeb177ecac0df318..ce30929f522de2c9a8f9e35dfce2255993b16ede 100644 --- a/src/share/vm/oops/instanceKlass.cpp +++ b/src/share/vm/oops/instanceKlass.cpp @@ -361,6 +361,9 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { set_protection_domain(NULL); set_signers(NULL); set_init_lock(NULL); + + // We should deallocate the Annotations instance + MetadataFactory::free_metadata(loader_data, annotations()); set_annotations(NULL); } diff --git a/src/share/vm/oops/instanceKlass.hpp b/src/share/vm/oops/instanceKlass.hpp index ddbdbd68024e687d4f5aa6d280cd9150257e3b9b..426486dd9654cc66868810e6f961ef7dc3f7fcfb 100644 --- a/src/share/vm/oops/instanceKlass.hpp +++ b/src/share/vm/oops/instanceKlass.hpp @@ -657,6 +657,10 @@ class InstanceKlass: public Klass { if (annotations() == NULL) return NULL; return annotations()->fields_annotations(); } + Annotations* type_annotations() const { + if (annotations() == NULL) return NULL; + return annotations()->type_annotations(); + } // allocation instanceOop allocate_instance(TRAPS); diff --git a/src/share/vm/oops/method.cpp b/src/share/vm/oops/method.cpp index 5818d58c29885a115199719e6d3c5cef89022e0a..c8aff7f36fdae162a52eceb6422bf7f5094e12cf 100644 --- a/src/share/vm/oops/method.cpp +++ b/src/share/vm/oops/method.cpp @@ -1331,13 +1331,15 @@ void Method::sort_methods(Array* methods, Array* methods_annotations, Array* methods_parameter_annotations, Array* methods_default_annotations, + Array* methods_type_annotations, bool idempotent) { int length = methods->length(); if (length > 1) { bool do_annotations = false; if (methods_annotations != NULL || methods_parameter_annotations != NULL || - methods_default_annotations != NULL) { + methods_default_annotations != NULL || + methods_type_annotations != NULL) { do_annotations = true; } if (do_annotations) { @@ -1356,6 +1358,7 @@ void Method::sort_methods(Array* methods, assert(methods_annotations == NULL || methods_annotations->length() == methods->length(), ""); assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), ""); assert(methods_default_annotations == NULL || methods_default_annotations->length() == methods->length(), ""); + assert(methods_type_annotations == NULL || methods_type_annotations->length() == methods->length(), ""); if (do_annotations) { ResourceMark rm; // Allocate temporary storage @@ -1363,6 +1366,7 @@ void Method::sort_methods(Array* methods, reorder_based_on_method_index(methods, methods_annotations, temp_array); reorder_based_on_method_index(methods, methods_parameter_annotations, temp_array); reorder_based_on_method_index(methods, methods_default_annotations, temp_array); + reorder_based_on_method_index(methods, methods_type_annotations, temp_array); } // Reset method ordering diff --git a/src/share/vm/oops/method.hpp b/src/share/vm/oops/method.hpp index ff7bc0ee53dda5d75e4673873c7a7b14c2a71326..5cf153197895ca48b99a94f0805a425c627a537f 100644 --- a/src/share/vm/oops/method.hpp +++ b/src/share/vm/oops/method.hpp @@ -228,6 +228,13 @@ class Method : public Metadata { } return ik->annotations()->get_method_default_annotations_of(method_idnum()); } + AnnotationArray* type_annotations() const { + InstanceKlass* ik = method_holder(); + Annotations* type_annos = ik->type_annotations(); + if (type_annos == NULL) + return NULL; + return type_annos->get_method_annotations_of(method_idnum()); +} #ifdef CC_INTERP void set_result_index(BasicType type); @@ -794,6 +801,7 @@ class Method : public Metadata { Array* methods_annotations, Array* methods_parameter_annotations, Array* methods_default_annotations, + Array* methods_type_annotations, bool idempotent = false); // size of parameters diff --git a/src/share/vm/prims/jvm.cpp b/src/share/vm/prims/jvm.cpp index c381674ffb54182753514bffdd0963d5d76c30f1..51d4a1d6e255fa4df7b99170812cb60aa456fb28 100644 --- a/src/share/vm/prims/jvm.cpp +++ b/src/share/vm/prims/jvm.cpp @@ -1573,6 +1573,23 @@ JVM_ENTRY(jbyteArray, JVM_GetMethodParameterAnnotations(JNIEnv *env, jobject met Annotations::make_java_array(m->parameter_annotations(), THREAD)); JVM_END +/* Type use annotations support (JDK 1.8) */ + +JVM_ENTRY(jbyteArray, JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls)) + assert (cls != NULL, "illegal class"); + JVMWrapper("JVM_GetClassTypeAnnotations"); + ResourceMark rm(THREAD); + // Return null for arrays and primitives + if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); + if (k->oop_is_instance()) { + typeArrayOop a = Annotations::make_java_array(InstanceKlass::cast(k)->type_annotations()->class_annotations(), CHECK_NULL); + return (jbyteArray) JNIHandles::make_local(env, a); + } + } + return NULL; +JVM_END + // New (JDK 1.4) reflection implementation ///////////////////////////////////// diff --git a/src/share/vm/prims/jvm.h b/src/share/vm/prims/jvm.h index 2bbc3db4dbca7f0e501c0ebdd914cec46c72e4ab..8dde7e900502ad3697c38e9031c6874b4d8708aa 100644 --- a/src/share/vm/prims/jvm.h +++ b/src/share/vm/prims/jvm.h @@ -519,6 +519,10 @@ JVM_GetMethodDefaultAnnotationValue(JNIEnv *env, jobject method); JNIEXPORT jbyteArray JNICALL JVM_GetMethodParameterAnnotations(JNIEnv *env, jobject method); +/* Type use annotations support (JDK 1.8) */ + +JNIEXPORT jbyteArray JNICALL +JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls); /* * New (JDK 1.4) reflection implementation diff --git a/src/share/vm/prims/jvmtiRedefineClasses.cpp b/src/share/vm/prims/jvmtiRedefineClasses.cpp index e3653000fea85e095407c9694df6f20848134801..6fb7243a872734fd4c32544157aa8410d482c27b 100644 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -3338,7 +3338,20 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, the_class->set_access_flags(flags); } - // Replace annotation fields value + // Since there is currently no rewriting of type annotations indexes + // into the CP, we null out type annotations on scratch_class before + // we swap annotations with the_class rather than facing the + // possibility of shipping annotations with broken indexes to + // Java-land. + Annotations* new_annotations = scratch_class->annotations(); + if (new_annotations != NULL) { + Annotations* new_type_annotations = new_annotations->type_annotations(); + if (new_type_annotations != NULL) { + MetadataFactory::free_metadata(scratch_class->class_loader_data(), new_type_annotations); + new_annotations->set_type_annotations(NULL); + } + } + // Swap annotation fields values Annotations* old_annotations = the_class->annotations(); the_class->set_annotations(scratch_class->annotations()); scratch_class->set_annotations(old_annotations); diff --git a/src/share/vm/runtime/fieldDescriptor.cpp b/src/share/vm/runtime/fieldDescriptor.cpp index 001d5d23e11ec66aaec5f4e2835a0c2dfc72877d..54a225a5ffe3ef045805bbafc8ee150115340ded 100644 --- a/src/share/vm/runtime/fieldDescriptor.cpp +++ b/src/share/vm/runtime/fieldDescriptor.cpp @@ -65,6 +65,17 @@ AnnotationArray* fieldDescriptor::annotations() const { return md->at(index()); } +AnnotationArray* fieldDescriptor::type_annotations() const { + InstanceKlass* ik = field_holder(); + Annotations* type_annos = ik->type_annotations(); + if (type_annos == NULL) + return NULL; + Array* md = type_annos->fields_annotations(); + if (md == NULL) + return NULL; + return md->at(index()); +} + constantTag fieldDescriptor::initial_value_tag() const { return constants()->tag_at(initial_value_index()); } diff --git a/src/share/vm/runtime/fieldDescriptor.hpp b/src/share/vm/runtime/fieldDescriptor.hpp index 00caf89844f17ba497cac1bf1812b9892ba255a2..12b75cab144bdd64f948d52822c7795f5140a3df 100644 --- a/src/share/vm/runtime/fieldDescriptor.hpp +++ b/src/share/vm/runtime/fieldDescriptor.hpp @@ -68,6 +68,7 @@ class fieldDescriptor VALUE_OBJ_CLASS_SPEC { Symbol* generic_signature() const; int index() const { return _index; } AnnotationArray* annotations() const; + AnnotationArray* type_annotations() const; // Initial field value bool has_initial_value() const { return field()->initval_index() != 0; } diff --git a/src/share/vm/runtime/reflection.cpp b/src/share/vm/runtime/reflection.cpp index 448266cde417e445bd51f8e5df8f86da8eebdfe4..7099d6c93962e62c4655075ceadeac45d419d470 100644 --- a/src/share/vm/runtime/reflection.cpp +++ b/src/share/vm/runtime/reflection.cpp @@ -771,6 +771,10 @@ oop Reflection::new_method(methodHandle method, bool intern_name, bool for_const typeArrayOop an_oop = Annotations::make_java_array(method->annotation_default(), CHECK_NULL); java_lang_reflect_Method::set_annotation_default(mh(), an_oop); } + if (java_lang_reflect_Method::has_type_annotations_field()) { + typeArrayOop an_oop = Annotations::make_java_array(method->type_annotations(), CHECK_NULL); + java_lang_reflect_Method::set_type_annotations(mh(), an_oop); + } return mh(); } @@ -849,6 +853,10 @@ oop Reflection::new_field(fieldDescriptor* fd, bool intern_name, TRAPS) { typeArrayOop an_oop = Annotations::make_java_array(fd->annotations(), CHECK_NULL); java_lang_reflect_Field::set_annotations(rh(), an_oop); } + if (java_lang_reflect_Field::has_type_annotations_field()) { + typeArrayOop an_oop = Annotations::make_java_array(fd->type_annotations(), CHECK_NULL); + java_lang_reflect_Field::set_type_annotations(rh(), an_oop); + } return rh(); }