70
70
import org .graalvm .nativeimage .hosted .InclusionCondition ;
71
71
import org .graalvm .nativeimage .hosted .RuntimeProxyCreation ;
72
72
import org .graalvm .nativeimage .hosted .RuntimeReflection ;
73
+ import org .graalvm .nativeimage .impl .RuntimeJNIAccessSupport ;
73
74
import org .graalvm .nativeimage .impl .RuntimeReflectionSupport ;
74
75
75
76
import com .oracle .graal .pointsto .ObjectScanner .ScanReason ;
94
95
import com .oracle .svm .hosted .annotation .AnnotationValue ;
95
96
import com .oracle .svm .hosted .annotation .SubstrateAnnotationExtractor ;
96
97
import com .oracle .svm .hosted .annotation .TypeAnnotationValue ;
98
+ import com .oracle .svm .hosted .jni .JNIAccessFeature ;
97
99
import com .oracle .svm .hosted .substitute .SubstitutionReflectivityFilter ;
98
100
import com .oracle .svm .util .LogUtils ;
99
101
import com .oracle .svm .util .ReflectionUtil ;
@@ -121,6 +123,7 @@ public class ReflectionDataBuilder extends ConditionalConfigurationRegistry impl
121
123
private final Map <Class <?>, Set <Class <?>>> innerClasses = new ConcurrentHashMap <>();
122
124
private final Map <Class <?>, Integer > enabledQueriesFlags = new ConcurrentHashMap <>();
123
125
private final Map <AnalysisType , Map <AnalysisField , ConditionalRuntimeValue <Field >>> registeredFields = new ConcurrentHashMap <>();
126
+ private final Set <Field > reflectiveAccessibleFields = new HashSet <>();
124
127
private final Set <AnalysisField > hidingFields = ConcurrentHashMap .newKeySet ();
125
128
private final Map <AnalysisType , Map <AnalysisMethod , ConditionalRuntimeValue <Executable >>> registeredMethods = new ConcurrentHashMap <>();
126
129
private final Map <AnalysisMethod , Object > methodAccessors = new ConcurrentHashMap <>();
@@ -471,6 +474,16 @@ private void registerMethod(InclusionCondition cnd, boolean queriedOnly, Executa
471
474
return accessor ;
472
475
});
473
476
}
477
+ /*
478
+ * We must register method that isn't registered as queriedOnly, as JNI accessible if it
479
+ * isn't already.
480
+ */
481
+ Set <Executable > JNIAccessibleMethods = JNIAccessFeature .singleton ().getJNIAccessibleMethods ();
482
+ Set <Class <?>> JNIAccessibleClasses = JNIAccessFeature .singleton ().getJNIAccessibleTypes ();
483
+
484
+ if (!JNIAccessibleMethods .contains (reflectExecutable ) && JNIAccessibleClasses .contains (declaringType .getJavaClass ()) && !queriedOnly ) {
485
+ ImageSingletons .lookup (RuntimeJNIAccessSupport .class ).register (cnd , false , reflectExecutable );
486
+ }
474
487
}
475
488
476
489
@ Override
@@ -512,6 +525,7 @@ public void registerAllFields(InclusionCondition condition, Class<?> clazz) {
512
525
registerAllFieldsQuery (condition , false , clazz );
513
526
}
514
527
528
+ @ Override
515
529
public void registerAllFieldsQuery (InclusionCondition condition , boolean queriedOnly , Class <?> clazz ) {
516
530
runConditionalInAnalysisTask (condition , (cnd ) -> {
517
531
for (Class <?> current = clazz ; current != null ; current = current .getSuperclass ()) {
@@ -530,6 +544,7 @@ public void registerAllDeclaredFields(InclusionCondition condition, Class<?> cla
530
544
registerAllDeclaredFieldsQuery (condition , false , clazz );
531
545
}
532
546
547
+ @ Override
533
548
public void registerAllDeclaredFieldsQuery (InclusionCondition condition , boolean queriedOnly , Class <?> clazz ) {
534
549
runConditionalInAnalysisTask (condition , (cnd ) -> {
535
550
setQueryFlag (clazz , ALL_DECLARED_FIELDS_FLAG );
@@ -595,6 +610,14 @@ private void registerField(InclusionCondition cnd, boolean queriedOnly, Field re
595
610
/* queryOnly methods are conditioned on the type itself */
596
611
cndValue .getConditions ().addCondition (cnd );
597
612
registerTypesForField (analysisField , reflectField , false );
613
+ reflectiveAccessibleFields .add (reflectField );
614
+ }
615
+
616
+ Set <Field > JNIAccessibleFields = JNIAccessFeature .singleton ().getJNIAccessibleFields ();
617
+ Set <Class <?>> JNIAccessibleClasses = JNIAccessFeature .singleton ().getJNIAccessibleTypes ();
618
+
619
+ if (!JNIAccessibleFields .contains (reflectField ) && JNIAccessibleClasses .contains (declaringClass .getJavaClass ()) && !queriedOnly ) {
620
+ ImageSingletons .lookup (RuntimeJNIAccessSupport .class ).register (cnd , false , reflectField );
598
621
}
599
622
}
600
623
@@ -1151,6 +1174,15 @@ public Object getAccessor(AnalysisMethod method) {
1151
1174
return methodAccessors .get (method );
1152
1175
}
1153
1176
1177
+ public Executable [] getNotQueriedOnlyExecutables (Class <?> declaringType ) {
1178
+ return methodAccessors .keySet ().stream ().filter (analysisMethod -> analysisMethod .getDeclaringClass ().getJavaClass ().equals (declaringType )).map (AnalysisMethod ::getJavaMethod )
1179
+ .collect (Collectors .toSet ()).toArray (new Executable [0 ]);
1180
+ }
1181
+
1182
+ public Field [] getReflectiveAccessibleFields (Class <?> declaringType ) {
1183
+ return reflectiveAccessibleFields .stream ().filter (field -> field .getDeclaringClass ().equals (declaringType )).collect (Collectors .toSet ()).toArray (new Field [0 ]);
1184
+ }
1185
+
1154
1186
@ Override
1155
1187
public Set <ResolvedJavaField > getHidingReflectionFields () {
1156
1188
assert sealed ;
0 commit comments