49
49
import java .security .ProtectionDomain ;
50
50
import java .security .cert .Certificate ;
51
51
import java .util .List ;
52
+ import java .util .Map ;
52
53
import java .util .Optional ;
53
54
import java .util .Set ;
54
55
import java .util .StringJoiner ;
67
68
import com .oracle .svm .core .annotate .Alias ;
68
69
import com .oracle .svm .core .annotate .Delete ;
69
70
import com .oracle .svm .core .annotate .Hybrid ;
71
+ import com .oracle .svm .core .annotate .Inject ;
70
72
import com .oracle .svm .core .annotate .KeepOriginal ;
73
+ import com .oracle .svm .core .annotate .RecomputeFieldValue ;
71
74
import com .oracle .svm .core .annotate .Substitute ;
72
75
import com .oracle .svm .core .annotate .TargetClass ;
73
76
import com .oracle .svm .core .annotate .TargetElement ;
@@ -1024,25 +1027,32 @@ public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)
1024
1027
*/
1025
1028
public static final class ReflectionData {
1026
1029
static final ReflectionData EMPTY = new ReflectionData (new Field [0 ], new Field [0 ], new Field [0 ], new Method [0 ], new Method [0 ], new Constructor <?>[0 ], new Constructor <?>[0 ], null , new Field [0 ],
1027
- new Method [0 ], new Class <?>[0 ], new Class <?>[0 ], null , null );
1030
+ new Method [0 ], new Class <?>[0 ], new Class <?>[0 ], null , null , null , null );
1028
1031
1029
1032
public static ReflectionData get (Field [] declaredFields , Field [] publicFields , Field [] publicUnhiddenFields , Method [] declaredMethods , Method [] publicMethods ,
1030
1033
Constructor <?>[] declaredConstructors , Constructor <?>[] publicConstructors , Constructor <?> nullaryConstructor , Field [] declaredPublicFields ,
1031
- Method [] declaredPublicMethods , Class <?>[] declaredClasses , Class <?>[] publicClasses , Executable enclosingMethodOrConstructor , Object [] recordComponents ) {
1034
+ Method [] declaredPublicMethods , Class <?>[] declaredClasses , Class <?>[] publicClasses , Executable enclosingMethodOrConstructor , Object [] recordComponents ,
1035
+ Map <String , Annotation []> recordAnnotations , Map <String , AnnotatedType > recordAnnotatedType ) {
1032
1036
1033
1037
if (z (declaredFields ) && z (publicFields ) && z (publicUnhiddenFields ) && z (declaredMethods ) && z (publicMethods ) && z (declaredConstructors ) &&
1034
1038
z (publicConstructors ) && nullaryConstructor == null && z (declaredPublicFields ) && z (declaredPublicMethods ) && z (declaredClasses ) &&
1035
- z (publicClasses ) && enclosingMethodOrConstructor == null && (recordComponents == null || z (recordComponents ))) {
1039
+ z (publicClasses ) && enclosingMethodOrConstructor == null && (recordComponents == null || z (recordComponents )) &&
1040
+ (recordAnnotations == null || e (recordAnnotations )) && (recordAnnotatedType == null || e (recordAnnotatedType ))) {
1036
1041
return EMPTY ; // avoid redundant objects in image heap
1037
1042
}
1038
1043
return new ReflectionData (declaredFields , publicFields , publicUnhiddenFields , declaredMethods , publicMethods , declaredConstructors , publicConstructors , nullaryConstructor ,
1039
- declaredPublicFields , declaredPublicMethods , declaredClasses , publicClasses , enclosingMethodOrConstructor , recordComponents );
1044
+ declaredPublicFields , declaredPublicMethods , declaredClasses , publicClasses , enclosingMethodOrConstructor , recordComponents , recordAnnotations ,
1045
+ recordAnnotatedType );
1040
1046
}
1041
1047
1042
1048
private static boolean z (Object [] array ) { // for better readability above
1043
1049
return array .length == 0 ;
1044
1050
}
1045
1051
1052
+ private static boolean e (Map <String , ?> map ) {
1053
+ return map .isEmpty ();
1054
+ }
1055
+
1046
1056
final Field [] declaredFields ;
1047
1057
final Field [] publicFields ;
1048
1058
final Field [] publicUnhiddenFields ;
@@ -1056,6 +1066,8 @@ private static boolean z(Object[] array) { // for better readability above
1056
1066
final Class <?>[] declaredClasses ;
1057
1067
final Class <?>[] publicClasses ;
1058
1068
final Object [] recordComponents ;
1069
+ final Map <String , Annotation []> recordAnnotations ; // component name => annotations
1070
+ final Map <String , AnnotatedType > recordAnnotatedType ; // component name => annotated type
1059
1071
1060
1072
/**
1061
1073
* The result of {@link Class#getEnclosingMethod()} or
@@ -1066,7 +1078,7 @@ private static boolean z(Object[] array) { // for better readability above
1066
1078
ReflectionData (Field [] declaredFields , Field [] publicFields , Field [] publicUnhiddenFields , Method [] declaredMethods , Method [] publicMethods , Constructor <?>[] declaredConstructors ,
1067
1079
Constructor <?>[] publicConstructors , Constructor <?> nullaryConstructor , Field [] declaredPublicFields , Method [] declaredPublicMethods , Class <?>[] declaredClasses ,
1068
1080
Class <?>[] publicClasses , Executable enclosingMethodOrConstructor ,
1069
- Object [] recordComponents ) {
1081
+ Object [] recordComponents , Map < String , Annotation []> recordAnnotations , Map < String , AnnotatedType > recordAnnotatedType ) {
1070
1082
this .declaredFields = declaredFields ;
1071
1083
this .publicFields = publicFields ;
1072
1084
this .publicUnhiddenFields = publicUnhiddenFields ;
@@ -1081,6 +1093,8 @@ private static boolean z(Object[] array) { // for better readability above
1081
1093
this .publicClasses = publicClasses ;
1082
1094
this .enclosingMethodOrConstructor = enclosingMethodOrConstructor ;
1083
1095
this .recordComponents = recordComponents ;
1096
+ this .recordAnnotations = recordAnnotations ;
1097
+ this .recordAnnotatedType = recordAnnotatedType ;
1084
1098
}
1085
1099
}
1086
1100
@@ -1218,11 +1232,21 @@ Method[] privateGetPublicMethods() {
1218
1232
@ TargetElement (onlyWith = JDK16OrLater .class )
1219
1233
private Target_java_lang_reflect_RecordComponent [] getRecordComponents0 () {
1220
1234
Object [] result = rd .recordComponents ;
1235
+ Map <String , Annotation []> annotations = rd .recordAnnotations ;
1236
+ Map <String , AnnotatedType > annotatedTypes = rd .recordAnnotatedType ;
1221
1237
if (result == null ) {
1222
1238
/* See ReflectionDataBuilder.buildRecordComponents() for details. */
1223
1239
throw VMError .unsupportedFeature ("Record components not available for record class " + getTypeName () + ". " +
1224
1240
"All record component accessor methods of this record class must be included in the reflection configuration at image build time, then this method can be called." );
1225
1241
}
1242
+ // Set component annotations for the the record-components
1243
+ for (Object rec : result ) {
1244
+ Target_java_lang_reflect_RecordComponent recordComp = (Target_java_lang_reflect_RecordComponent ) rec ;
1245
+ Annotation [] annot = annotations .get (recordComp .getName ());
1246
+ AnnotatedType type = annotatedTypes .get (recordComp .getName ());
1247
+ recordComp .componentAnnotations = annot ;
1248
+ recordComp .annotatedType = type ;
1249
+ }
1226
1250
return (Target_java_lang_reflect_RecordComponent []) result ;
1227
1251
}
1228
1252
@@ -1671,4 +1695,41 @@ final class Target_jdk_internal_reflect_ConstantPool {
1671
1695
1672
1696
@ TargetClass (className = "java.lang.reflect.RecordComponent" , onlyWith = JDK16OrLater .class )
1673
1697
final class Target_java_lang_reflect_RecordComponent {
1698
+
1699
+ @ Inject //
1700
+ @ RecomputeFieldValue (kind = RecomputeFieldValue .Kind .Reset ) //
1701
+ volatile Annotation [] componentAnnotations ;
1702
+
1703
+ @ Inject //
1704
+ @ RecomputeFieldValue (kind = RecomputeFieldValue .Kind .Reset ) //
1705
+ volatile AnnotatedType annotatedType ;
1706
+
1707
+ @ Substitute //
1708
+ public Annotation [] getAnnotations () {
1709
+ return componentAnnotations ;
1710
+ }
1711
+
1712
+ @ Substitute //
1713
+ public Annotation [] getDeclaredAnnotations () {
1714
+ return componentAnnotations ;
1715
+ }
1716
+
1717
+ @ Substitute //
1718
+ public Annotation getAnnotation (Class <?> annotationClass ) {
1719
+ for (Annotation ann : componentAnnotations ) {
1720
+ if (annotationClass .isAssignableFrom (ann .annotationType ())) {
1721
+ return ann ;
1722
+ }
1723
+ }
1724
+ return null ;
1725
+ }
1726
+
1727
+ @ Substitute //
1728
+ public AnnotatedType getAnnotatedType () {
1729
+ return annotatedType ;
1730
+ }
1731
+
1732
+ @ Alias //
1733
+ public native String getName ();
1734
+
1674
1735
}
0 commit comments