Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,11 @@ public interface RuntimeReflectionSupport extends ReflectionRegistry {
Object getAccessor(Executable method);

/*
* Returns the methods that shadow a superclass method registered for reflection, to be excluded
* from reflection queries.
* Returns the methods and fields that shadow a superclass element registered for reflection, to
* be excluded from reflection queries.
*/
Set<?> getHidingReflectionFields();

Set<?> getHidingReflectionMethods();

Object[] getRecordComponents(Class<?> type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.lang.reflect.Field;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
Expand All @@ -49,6 +50,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.StringJoiner;

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

@KeepOriginal
private native Field getField(@SuppressWarnings("hiding") String name) throws NoSuchMethodException;
@Substitute
public Field getField(String fieldName) throws NoSuchFieldException, SecurityException {
Objects.requireNonNull(fieldName);
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
}
Field field = getField0(fieldName);
if (field == null || ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHiding(field.getModifiers())) {
throw new NoSuchFieldException(fieldName);
}
return getReflectionFactory().copyField(field);
}

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

@KeepOriginal
private native Field getDeclaredField(@SuppressWarnings("hiding") String name);
/**
* @see #filterHidingFields(Field...)
*/
@Substitute
public Field getDeclaredField(String fieldName) throws NoSuchFieldException, SecurityException {
Objects.requireNonNull(fieldName);
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
}
Field field = searchFields(privateGetDeclaredFields(false), fieldName);
if (field == null || ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHiding(field.getModifiers())) {
throw new NoSuchFieldException(fieldName);
}
return getReflectionFactory().copyField(field);
}

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

@KeepOriginal
private static native Field[] copyFields(Field[] arg);
/**
* @see #filterHidingFields(Field...)
*/
@Substitute
private static Field[] copyFields(Field[] original) {
Field[] arg = filterHidingFields(original);
Field[] out = new Field[arg.length];
ReflectionFactory fact = getReflectionFactory();
for (int i = 0; i < arg.length; i++) {
out[i] = fact.copyField(arg[i]);
}
return out;
}

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

/*
* We need to filter out hiding methods at the last moment. This ensures that the JDK internals
* see them as regular methods and ensure the visibility of methods is correct, but they should
* not be returned to application code.
* We need to filter out hiding elements at the last moment. This ensures that the JDK internals
* see them as regular methods and fields and ensure their visibility is correct, but they
* should not be returned to application code.
*/
private static Field[] filterHidingFields(Field... fields) {
List<Field> filtered = new ArrayList<>();
for (Field field : fields) {
if (!ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHiding(field.getModifiers())) {
filtered.add(field);
}
}
return filtered.toArray(new Field[0]);
}

private static Method[] filterHidingMethods(Method... methods) {
List<Method> filtered = new ArrayList<>();
for (Method method : methods) {
if (!ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHidingMethod(method.getModifiers())) {
if (!ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHiding(method.getModifiers())) {
filtered.add(method);
}
}
Expand Down Expand Up @@ -1687,7 +1737,7 @@ Method getMostSpecific() {
}
}
/* Filter out hiding methods after the retursive lookup is done */
return ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHidingMethod(m.getModifiers()) ? null : m;
return ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHiding(m.getModifiers()) ? null : m;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public interface ReflectionMetadataDecoder {

byte[] parseByteArray(int index);

boolean isHidingMethod(int modifiers);
boolean isHiding(int modifiers);

long getMetadataByteLength();
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import static com.oracle.svm.core.util.VMError.shouldNotReachHere;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
Expand Down Expand Up @@ -60,6 +59,7 @@
import org.graalvm.word.WordFactory;

import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.meta.AnalysisField;
import com.oracle.graal.pointsto.meta.AnalysisMethod;
import com.oracle.objectfile.ObjectFile;
import com.oracle.svm.core.SubstrateOptions;
Expand Down Expand Up @@ -255,25 +255,34 @@ public void buildRuntimeMetadata(CFunctionPointer firstMethod, UnsignedWord code

Set<HostedField> includedFields = new HashSet<>();
Set<HostedMethod> includedMethods = new HashSet<>();
Set<Field> configurationFields = reflectionSupport.getReflectionFields();
Set<Executable> configurationExecutables = reflectionSupport.getReflectionExecutables();

for (AccessibleObject object : reflectionSupport.getHeapReflectionObjects()) {
if (object instanceof Field) {
includedFields.add(hMetaAccess.lookupJavaField((Field) object));
} else if (object instanceof Method || object instanceof Constructor) {
includedMethods.add(hMetaAccess.lookupJavaMethod((Executable) object));
HostedField hostedField = hMetaAccess.lookupJavaField((Field) object);
if (!includedFields.contains(hostedField)) {
reflectionMetadataEncoder.addHeapAccessibleObjectMetadata(hMetaAccess, object, configurationFields.contains(object));
includedFields.add(hostedField);
}
} else if (object instanceof Executable) {
HostedMethod hostedMethod = hMetaAccess.lookupJavaMethod((Executable) object);
if (!includedMethods.contains(hostedMethod)) {
reflectionMetadataEncoder.addHeapAccessibleObjectMetadata(hMetaAccess, object, configurationExecutables.contains(object));
includedMethods.add(hostedMethod);
}
}
reflectionMetadataEncoder.addHeapAccessibleObjectMetadata(hMetaAccess, object);
}

for (Field reflectField : reflectionSupport.getReflectionFields()) {
for (Field reflectField : configurationFields) {
HostedField field = hMetaAccess.lookupJavaField(reflectField);
if (!includedFields.contains(field)) {
reflectionMetadataEncoder.addReflectionFieldMetadata(hMetaAccess, field, reflectField);
includedFields.add(field);
}
}

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

for (Object field : reflectionSupport.getHidingReflectionFields()) {
AnalysisField hidingField = (AnalysisField) field;
HostedField hostedField = hUniverse.optionalLookup(hidingField);
if (hostedField == null || !includedFields.contains(hostedField)) {
HostedType declaringType = hUniverse.lookup(hidingField.getDeclaringClass());
String name = hidingField.getName();
HostedType type = hUniverse.lookup(hidingField.getType());
int modifiers = hidingField.getModifiers();
reflectionMetadataEncoder.addHidingFieldMetadata(hidingField, declaringType, name, type, modifiers);
if (hostedField != null) {
includedFields.add(hostedField);
}
}
}

for (Object method : reflectionSupport.getHidingReflectionMethods()) {
AnalysisMethod hidingMethod = (AnalysisMethod) method;
HostedMethod hostedMethod = hUniverse.optionalLookup(hidingMethod);
Expand Down Expand Up @@ -622,7 +646,9 @@ public interface ReflectionMetadataEncoder {

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

void addHeapAccessibleObjectMetadata(MetaAccessProvider metaAccess, AccessibleObject object);
void addHeapAccessibleObjectMetadata(MetaAccessProvider metaAccess, AccessibleObject object, boolean registered);

void addHidingFieldMetadata(AnalysisField analysisField, HostedType declType, String name, HostedType type, int modifiers);

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,10 @@ public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)

@Override
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
return original.getDeclaredAnnotation(annotationClass);
if (annotationClass == LambdaFormHiddenMethod.class) {
return annotationClass.cast(LambdaFormHiddenMethod.Holder.INSTANCE);
}
return null;
}

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

@Override
public Annotation[] getDeclaredAnnotations() {
return original.getDeclaredAnnotations();
return LambdaFormHiddenMethod.Holder.ARRAY;
}

public ResolvedJavaType getOriginal() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.oracle.graal.pointsto.meta.AnalysisMethod;
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
import com.oracle.svm.core.annotate.Delete;
import com.oracle.svm.core.annotate.InjectAccessors;
import com.oracle.svm.core.annotate.TargetClass;

import jdk.vm.ci.meta.ResolvedJavaType;
Expand Down Expand Up @@ -86,7 +87,7 @@ public static boolean shouldExclude(Field field, AnalysisMetaAccess metaAccess,
if (!universe.hostVM().platformSupported(aField)) {
return true;
}
if (aField.isAnnotationPresent(Delete.class)) {
if (aField.isAnnotationPresent(Delete.class) || aField.isAnnotationPresent(InjectAccessors.class)) {
return true; // accesses would fail at runtime
}
} catch (UnsupportedFeatureException ignored) {
Expand Down
Loading