mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8004823: Add VM support for type annotation reflection
Reviewed-by: dholmes, coleenp
This commit is contained in:
parent
9c761152db
commit
6ed6cb5375
22 changed files with 302 additions and 11 deletions
|
@ -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<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
|
|||
bool is_interface,
|
||||
FieldAllocationCount *fac,
|
||||
Array<AnnotationArray*>** fields_annotations,
|
||||
Array<AnnotationArray*>** fields_type_annotations,
|
||||
u2* java_fields_count_ptr, TRAPS) {
|
||||
ClassFileStream* cfs = stream();
|
||||
cfs->guarantee_more(2, CHECK_NULL); // length
|
||||
|
@ -1119,6 +1141,7 @@ Array<u2>* 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<u2>* 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<u2>* 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<AnnotationArray*>(
|
||||
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<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
|||
Array<AnnotationArray*>** methods_annotations,
|
||||
Array<AnnotationArray*>** methods_parameter_annotations,
|
||||
Array<AnnotationArray*>** methods_default_annotations,
|
||||
Array<AnnotationArray*>** 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<Method*>* 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<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
|||
MetadataFactory::new_array<AnnotationArray*>(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<AnnotationArray*>(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<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
|
|||
Array<AnnotationArray*>* methods_annotations,
|
||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
||||
Array<AnnotationArray*>* methods_default_annotations,
|
||||
Array<AnnotationArray*>* 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<int>* 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<AnnotationArray*>* fields_annotations = NULL;
|
||||
Array<AnnotationArray*>* fields_type_annotations = NULL;
|
||||
Array<u2>* 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<AnnotationArray*>* methods_annotations = NULL;
|
||||
Array<AnnotationArray*>* methods_parameter_annotations = NULL;
|
||||
Array<AnnotationArray*>* methods_default_annotations = NULL;
|
||||
Array<AnnotationArray*>* methods_type_annotations = NULL;
|
||||
Array<Method*>* 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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue