Skip to content

Commit 9a2700e

Browse files
committed
Fix reflection metadata-related test failures
1 parent e6a0556 commit 9a2700e

File tree

11 files changed

+327
-100
lines changed

11 files changed

+327
-100
lines changed

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeReflectionSupport.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,11 @@ public interface RuntimeReflectionSupport extends ReflectionRegistry {
5656
Object getAccessor(Executable method);
5757

5858
/*
59-
* Returns the methods that shadow a superclass method registered for reflection, to be excluded
60-
* from reflection queries.
59+
* Returns the methods and fields that shadow a superclass element registered for reflection, to
60+
* be excluded from reflection queries.
6161
*/
62+
Set<?> getHidingReflectionFields();
63+
6264
Set<?> getHidingReflectionMethods();
6365

6466
Object[] getRecordComponents(Class<?> type);

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import java.lang.reflect.Field;
4040
import java.lang.reflect.GenericDeclaration;
4141
import java.lang.reflect.InvocationTargetException;
42+
import java.lang.reflect.Member;
4243
import java.lang.reflect.Method;
4344
import java.lang.reflect.Modifier;
4445
import java.lang.reflect.Type;
@@ -49,6 +50,7 @@
4950
import java.util.Arrays;
5051
import java.util.Collection;
5152
import java.util.List;
53+
import java.util.Objects;
5254
import java.util.Optional;
5355
import java.util.StringJoiner;
5456

@@ -899,8 +901,20 @@ public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
899901
@KeepOriginal
900902
private native Constructor<?>[] getConstructors();
901903

902-
@KeepOriginal
903-
private native Field getField(@SuppressWarnings("hiding") String name) throws NoSuchMethodException;
904+
@Substitute
905+
public Field getField(String fieldName) throws NoSuchFieldException, SecurityException {
906+
Objects.requireNonNull(fieldName);
907+
@SuppressWarnings("removal")
908+
SecurityManager sm = System.getSecurityManager();
909+
if (sm != null) {
910+
checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
911+
}
912+
Field field = getField0(fieldName);
913+
if (field == null || ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHiding(field.getModifiers())) {
914+
throw new NoSuchFieldException(fieldName);
915+
}
916+
return getReflectionFactory().copyField(field);
917+
}
904918

905919
@KeepOriginal
906920
private native Method getMethod(@SuppressWarnings("hiding") String name, Class<?>... parameterTypes) throws NoSuchMethodException;
@@ -923,8 +937,23 @@ public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
923937
@KeepOriginal
924938
private native Constructor<?>[] getDeclaredConstructors();
925939

926-
@KeepOriginal
927-
private native Field getDeclaredField(@SuppressWarnings("hiding") String name);
940+
/**
941+
* @see #filterHidingFields(Field...)
942+
*/
943+
@Substitute
944+
public Field getDeclaredField(String fieldName) throws NoSuchFieldException, SecurityException {
945+
Objects.requireNonNull(fieldName);
946+
@SuppressWarnings("removal")
947+
SecurityManager sm = System.getSecurityManager();
948+
if (sm != null) {
949+
checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
950+
}
951+
Field field = searchFields(privateGetDeclaredFields(false), fieldName);
952+
if (field == null || ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHiding(field.getModifiers())) {
953+
throw new NoSuchFieldException(fieldName);
954+
}
955+
return getReflectionFactory().copyField(field);
956+
}
928957

929958
@KeepOriginal
930959
private native Method getDeclaredMethod(@SuppressWarnings("hiding") String name, Class<?>... parameterTypes);
@@ -1009,8 +1038,19 @@ private static Method searchMethods(Method[] allMethods, String name, Class<?>[]
10091038
@KeepOriginal
10101039
private static native boolean arrayContentsEq(Object[] a1, Object[] a2);
10111040

1012-
@KeepOriginal
1013-
private static native Field[] copyFields(Field[] arg);
1041+
/**
1042+
* @see #filterHidingFields(Field...)
1043+
*/
1044+
@Substitute
1045+
private static Field[] copyFields(Field[] original) {
1046+
Field[] arg = filterHidingFields(original);
1047+
Field[] out = new Field[arg.length];
1048+
ReflectionFactory fact = getReflectionFactory();
1049+
for (int i = 0; i < arg.length; i++) {
1050+
out[i] = fact.copyField(arg[i]);
1051+
}
1052+
return out;
1053+
}
10141054

10151055
/**
10161056
* @see #filterHidingMethods(Method...)
@@ -1463,14 +1503,24 @@ private Class<?>[] getPermittedSubclasses0() {
14631503
private native boolean isDirectSubType(Class<?> c);
14641504

14651505
/*
1466-
* We need to filter out hiding methods at the last moment. This ensures that the JDK internals
1467-
* see them as regular methods and ensure the visibility of methods is correct, but they should
1468-
* not be returned to application code.
1506+
* We need to filter out hiding elements at the last moment. This ensures that the JDK internals
1507+
* see them as regular methods and fields and ensure their visibility is correct, but they
1508+
* should not be returned to application code.
14691509
*/
1510+
private static Field[] filterHidingFields(Field... fields) {
1511+
List<Field> filtered = new ArrayList<>();
1512+
for (Field field : fields) {
1513+
if (!ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHiding(field.getModifiers())) {
1514+
filtered.add(field);
1515+
}
1516+
}
1517+
return filtered.toArray(new Field[0]);
1518+
}
1519+
14701520
private static Method[] filterHidingMethods(Method... methods) {
14711521
List<Method> filtered = new ArrayList<>();
14721522
for (Method method : methods) {
1473-
if (!ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHidingMethod(method.getModifiers())) {
1523+
if (!ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHiding(method.getModifiers())) {
14741524
filtered.add(method);
14751525
}
14761526
}
@@ -1687,7 +1737,7 @@ Method getMostSpecific() {
16871737
}
16881738
}
16891739
/* Filter out hiding methods after the retursive lookup is done */
1690-
return ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHidingMethod(m.getModifiers()) ? null : m;
1740+
return ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHiding(m.getModifiers()) ? null : m;
16911741
}
16921742
}
16931743

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/ReflectionMetadataDecoder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public interface ReflectionMetadataDecoder {
5151

5252
byte[] parseByteArray(int index);
5353

54-
boolean isHidingMethod(int modifiers);
54+
boolean isHiding(int modifiers);
5555

5656
long getMetadataByteLength();
5757
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import static com.oracle.svm.core.util.VMError.shouldNotReachHere;
2828

2929
import java.lang.reflect.AccessibleObject;
30-
import java.lang.reflect.Constructor;
3130
import java.lang.reflect.Executable;
3231
import java.lang.reflect.Field;
3332
import java.lang.reflect.Method;
@@ -60,6 +59,7 @@
6059
import org.graalvm.word.WordFactory;
6160

6261
import com.oracle.graal.pointsto.BigBang;
62+
import com.oracle.graal.pointsto.meta.AnalysisField;
6363
import com.oracle.graal.pointsto.meta.AnalysisMethod;
6464
import com.oracle.objectfile.ObjectFile;
6565
import com.oracle.svm.core.SubstrateOptions;
@@ -255,25 +255,34 @@ public void buildRuntimeMetadata(CFunctionPointer firstMethod, UnsignedWord code
255255

256256
Set<HostedField> includedFields = new HashSet<>();
257257
Set<HostedMethod> includedMethods = new HashSet<>();
258+
Set<Field> configurationFields = reflectionSupport.getReflectionFields();
259+
Set<Executable> configurationExecutables = reflectionSupport.getReflectionExecutables();
258260

259261
for (AccessibleObject object : reflectionSupport.getHeapReflectionObjects()) {
260262
if (object instanceof Field) {
261-
includedFields.add(hMetaAccess.lookupJavaField((Field) object));
262-
} else if (object instanceof Method || object instanceof Constructor) {
263-
includedMethods.add(hMetaAccess.lookupJavaMethod((Executable) object));
263+
HostedField hostedField = hMetaAccess.lookupJavaField((Field) object);
264+
if (!includedFields.contains(hostedField)) {
265+
reflectionMetadataEncoder.addHeapAccessibleObjectMetadata(hMetaAccess, object, configurationFields.contains(object));
266+
includedFields.add(hostedField);
267+
}
268+
} else if (object instanceof Executable) {
269+
HostedMethod hostedMethod = hMetaAccess.lookupJavaMethod((Executable) object);
270+
if (!includedMethods.contains(hostedMethod)) {
271+
reflectionMetadataEncoder.addHeapAccessibleObjectMetadata(hMetaAccess, object, configurationExecutables.contains(object));
272+
includedMethods.add(hostedMethod);
273+
}
264274
}
265-
reflectionMetadataEncoder.addHeapAccessibleObjectMetadata(hMetaAccess, object);
266275
}
267276

268-
for (Field reflectField : reflectionSupport.getReflectionFields()) {
277+
for (Field reflectField : configurationFields) {
269278
HostedField field = hMetaAccess.lookupJavaField(reflectField);
270279
if (!includedFields.contains(field)) {
271280
reflectionMetadataEncoder.addReflectionFieldMetadata(hMetaAccess, field, reflectField);
272281
includedFields.add(field);
273282
}
274283
}
275284

276-
for (Executable reflectMethod : reflectionSupport.getReflectionExecutables()) {
285+
for (Executable reflectMethod : configurationExecutables) {
277286
HostedMethod method = hMetaAccess.lookupJavaMethod(reflectMethod);
278287
if (!includedMethods.contains(method)) {
279288
Object accessor = reflectionSupport.getAccessor(reflectMethod);
@@ -282,6 +291,21 @@ public void buildRuntimeMetadata(CFunctionPointer firstMethod, UnsignedWord code
282291
}
283292
}
284293

294+
for (Object field : reflectionSupport.getHidingReflectionFields()) {
295+
AnalysisField hidingField = (AnalysisField) field;
296+
HostedField hostedField = hUniverse.optionalLookup(hidingField);
297+
if (hostedField == null || !includedFields.contains(hostedField)) {
298+
HostedType declaringType = hUniverse.lookup(hidingField.getDeclaringClass());
299+
String name = hidingField.getName();
300+
HostedType type = hUniverse.lookup(hidingField.getType());
301+
int modifiers = hidingField.getModifiers();
302+
reflectionMetadataEncoder.addHidingFieldMetadata(hidingField, declaringType, name, type, modifiers);
303+
if (hostedField != null) {
304+
includedFields.add(hostedField);
305+
}
306+
}
307+
}
308+
285309
for (Object method : reflectionSupport.getHidingReflectionMethods()) {
286310
AnalysisMethod hidingMethod = (AnalysisMethod) method;
287311
HostedMethod hostedMethod = hUniverse.optionalLookup(hidingMethod);
@@ -622,7 +646,9 @@ public interface ReflectionMetadataEncoder {
622646

623647
void addReflectionExecutableMetadata(MetaAccessProvider metaAccess, HostedMethod sharedMethod, Executable reflectMethod, Object accessor);
624648

625-
void addHeapAccessibleObjectMetadata(MetaAccessProvider metaAccess, AccessibleObject object);
649+
void addHeapAccessibleObjectMetadata(MetaAccessProvider metaAccess, AccessibleObject object, boolean registered);
650+
651+
void addHidingFieldMetadata(AnalysisField analysisField, HostedType declType, String name, HostedType type, int modifiers);
626652

627653
void addHidingMethodMetadata(AnalysisMethod analysisMethod, HostedType declType, String name, HostedType[] paramTypes, int modifiers, HostedType returnType);
628654

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/lambda/LambdaSubstitutionType.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,10 @@ public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
399399

400400
@Override
401401
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
402-
return original.getDeclaredAnnotation(annotationClass);
402+
if (annotationClass == LambdaFormHiddenMethod.class) {
403+
return annotationClass.cast(LambdaFormHiddenMethod.Holder.INSTANCE);
404+
}
405+
return null;
403406
}
404407

405408
@Override
@@ -409,7 +412,7 @@ public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotati
409412

410413
@Override
411414
public Annotation[] getDeclaredAnnotations() {
412-
return original.getDeclaredAnnotations();
415+
return LambdaFormHiddenMethod.Holder.ARRAY;
413416
}
414417

415418
public ResolvedJavaType getOriginal() {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/SubstitutionReflectivityFilter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.oracle.graal.pointsto.meta.AnalysisMethod;
3434
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
3535
import com.oracle.svm.core.annotate.Delete;
36+
import com.oracle.svm.core.annotate.InjectAccessors;
3637
import com.oracle.svm.core.annotate.TargetClass;
3738

3839
import jdk.vm.ci.meta.ResolvedJavaType;
@@ -86,7 +87,7 @@ public static boolean shouldExclude(Field field, AnalysisMetaAccess metaAccess,
8687
if (!universe.hostVM().platformSupported(aField)) {
8788
return true;
8889
}
89-
if (aField.isAnnotationPresent(Delete.class)) {
90+
if (aField.isAnnotationPresent(Delete.class) || aField.isAnnotationPresent(InjectAccessors.class)) {
9091
return true; // accesses would fail at runtime
9192
}
9293
} catch (UnsupportedFeatureException ignored) {

0 commit comments

Comments
 (0)