package com.oracle.svm.core.hub;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.ref.Reference;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
import org.graalvm.compiler.core.common.SuppressFBWarnings;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.ProcessProperties;
import org.graalvm.nativeimage.c.function.CFunctionPointer;
import org.graalvm.util.DirectAnnotationAccess;
import com.oracle.svm.core.RuntimeAssertionsSupport;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.Delete;
import com.oracle.svm.core.annotate.Hybrid;
import com.oracle.svm.core.annotate.KeepOriginal;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.annotate.TargetElement;
import com.oracle.svm.core.annotate.Uninterruptible;
import com.oracle.svm.core.annotate.UnknownObjectField;
import com.oracle.svm.core.classinitialization.ClassInitializationInfo;
import com.oracle.svm.core.classinitialization.EnsureClassInitializedNode;
import com.oracle.svm.core.jdk.JDK11OrLater;
import com.oracle.svm.core.jdk.JDK15OrLater;
import com.oracle.svm.core.jdk.JDK8OrEarlier;
import com.oracle.svm.core.jdk.Package_jdk_internal_reflect;
import com.oracle.svm.core.jdk.Resources;
import com.oracle.svm.core.jdk.Target_java_lang_Module;
import com.oracle.svm.core.meta.SharedType;
import com.oracle.svm.core.util.LazyFinalReference;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.util.ReflectionUtil;
import com.oracle.svm.util.ReflectionUtil.ReflectionUtilError;
import jdk.vm.ci.meta.JavaKind;
import sun.security.util.SecurityConstants;
@Hybrid
@Substitute
@TargetClass(java.lang.Class.class)
@SuppressWarnings({"static-method", "serial"})
@SuppressFBWarnings(value = "Se", justification = "DynamicHub must implement Serializable for compatibility with java.lang.Class, not because of actual serialization")
public final class DynamicHub implements JavaKind.FormatWithToString, AnnotatedElement, java.lang.reflect.Type, GenericDeclaration, Serializable {
@Substitute
@TargetElement(onlyWith = JDK11OrLater.class)
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
private static final int SYNTHETIC = 0x00001000;
@Platforms(Platform.HOSTED_ONLY.class)
private final Class<?> hostedJavaClass;
private String name;
private int hubType;
private byte referenceType;
private int layoutEncoding;
private int typeID;
private short typeCheckStart;
private short typeCheckRange;
private short typeCheckSlot;
private int monitorOffset;
private boolean isLocalClass;
private boolean isInstantiated;
private Object isAnonymousClass;
private boolean isHidden;
private boolean isRecord;
private final boolean assertionStatus;
private final int modifiers;
private final DynamicHub superHub;
private final DynamicHub componentHub;
private DynamicHub arrayHub;
private DynamicHub enclosingClass;
private Object interfacesEncoding;
private Object enumConstantsReference;
private int referenceMapIndex;
private SharedType metaType;
private String sourceFileName;
private Object annotationsEncoding;
private boolean hasDefaultMethods;
private boolean declaresDefaultMethods;
private ClassInitializationInfo classInitializationInfo;
private final ClassLoader classLoader;
@Hybrid.TypeIDSlots private short[] typeCheckSlots;
@Hybrid.Array private CFunctionPointer[] vtable;
private GenericInfo genericInfo;
private AnnotatedSuperInfo annotatedSuperInfo;
private Object module;
private final Class<?> nestHost;
@Platforms(Platform.HOSTED_ONLY.class)
public void setModule(Object module) {
this.module = module;
}
private static final LazyFinalReference<java.security.ProtectionDomain> allPermDomainReference = new LazyFinalReference<>(() -> {
java.security.Permissions perms = new java.security.Permissions();
perms.add(SecurityConstants.ALL_PERMISSION);
CodeSource cs;
try {
cs = new CodeSource(new File(ProcessProperties.getExecutableName()).toURI().toURL(), (Certificate[]) null);
} catch (MalformedURLException ex) {
cs = null;
}
return new java.security.ProtectionDomain(cs, perms);
});
public static final LazyFinalReference<Target_java_lang_Module> singleModuleReference = new LazyFinalReference<>(Target_java_lang_Module::new);
private final LazyFinalReference<String> packageNameReference = new LazyFinalReference<>(this::computePackageName);
@Platforms(Platform.HOSTED_ONLY.class)
public DynamicHub(Class<?> hostedJavaClass, String name, HubType hubType, ReferenceType referenceType, boolean isLocalClass, Object isAnonymousClass, DynamicHub superType, DynamicHub componentHub,
String sourceFileName, int modifiers, ClassLoader classLoader, boolean isHidden, boolean isRecord, Class<?> nestHost, boolean assertionStatus) {
this.hostedJavaClass = hostedJavaClass;
this.name = name;
this.hubType = hubType.getValue();
this.referenceType = referenceType.getValue();
this.isLocalClass = isLocalClass;
this.isAnonymousClass = isAnonymousClass;
this.superHub = superType;
this.componentHub = componentHub;
this.sourceFileName = sourceFileName;
this.modifiers = modifiers;
this.classLoader = classLoader;
this.isHidden = isHidden;
this.isRecord = isRecord;
this.nestHost = nestHost;
this.assertionStatus = assertionStatus;
}
@Platforms(Platform.HOSTED_ONLY.class)
public void setClassInitializationInfo(ClassInitializationInfo classInitializationInfo, boolean hasDefaultMethods, boolean declaresDefaultMethods) {
this.classInitializationInfo = classInitializationInfo;
this.hasDefaultMethods = hasDefaultMethods;
this.declaresDefaultMethods = declaresDefaultMethods;
}
@Platforms(Platform.HOSTED_ONLY.class)
public void setClassInitializationInfo(ClassInitializationInfo classInitializationInfo) {
this.classInitializationInfo = classInitializationInfo;
}
@Platforms(Platform.HOSTED_ONLY.class)
public void setData(int layoutEncoding, int typeID, int monitorOffset,
short typeCheckStart, short typeCheckRange, short typeCheckSlot, short[] typeCheckSlots,
CFunctionPointer[] vtable, long referenceMapIndex, boolean isInstantiated) {
this.layoutEncoding = layoutEncoding;
this.typeID = typeID;
this.monitorOffset = monitorOffset;
this.typeCheckStart = typeCheckStart;
this.typeCheckRange = typeCheckRange;
this.typeCheckSlot = typeCheckSlot;
this.typeCheckSlots = typeCheckSlots;
this.vtable = vtable;
if ((int) referenceMapIndex != referenceMapIndex) {
throw VMError.shouldNotReachHere("Reference map index not within integer range, need to switch field from int to long");
}
this.referenceMapIndex = (int) referenceMapIndex;
this.isInstantiated = isInstantiated;
}
@Platforms(Platform.HOSTED_ONLY.class)
public void setArrayHub(DynamicHub arrayHub) {
assert (this.arrayHub == null || this.arrayHub == arrayHub) && arrayHub != null;
assert arrayHub.getComponentHub() == this;
this.arrayHub = arrayHub;
}
@Platforms(Platform.HOSTED_ONLY.class)
public void setEnclosingClass(DynamicHub enclosingClass) {
assert (this.enclosingClass == null || this.enclosingClass == enclosingClass) && enclosingClass != null;
this.enclosingClass = enclosingClass;
}
@Platforms(Platform.HOSTED_ONLY.class)
public void setGenericInfo(GenericInfo genericInfo) {
this.genericInfo = genericInfo;
}
@Platforms(Platform.HOSTED_ONLY.class)
public GenericInfo getGenericInfo() {
return genericInfo;
}
@Platforms(Platform.HOSTED_ONLY.class)
public void setAnnotatedSuperInfo(AnnotatedSuperInfo annotatedSuperInfo) {
this.annotatedSuperInfo = annotatedSuperInfo;
}
@Platforms(Platform.HOSTED_ONLY.class)
public AnnotatedSuperInfo getAnnotatedSuperInfo() {
return annotatedSuperInfo;
}
@Platforms(Platform.HOSTED_ONLY.class)
public void setInterfacesEncoding(Object interfacesEncoding) {
this.interfacesEncoding = interfacesEncoding;
}
@Platforms(Platform.HOSTED_ONLY.class)
public Object getInterfacesEncoding() {
return interfacesEncoding;
}
@Platforms(Platform.HOSTED_ONLY.class)
public void setAnnotationsEncoding(Object annotationsEncoding) {
this.annotationsEncoding = annotationsEncoding;
}
@Platforms(Platform.HOSTED_ONLY.class)
public Object getAnnotationsEncoding() {
return annotationsEncoding;
}
@Platforms(Platform.HOSTED_ONLY.class)
public boolean shouldInitEnumConstants() {
return enumConstantsReference == null;
}
@Platforms(Platform.HOSTED_ONLY.class)
public void initEnumConstants(Enum<?>[] enumConstants) {
enumConstantsReference = enumConstants;
}
@Platforms(Platform.HOSTED_ONLY.class)
public void initEnumConstantsAtRuntime(Class<?> enumClass) {
try {
Method values = ReflectionUtil.lookupMethod(enumClass, "values");
enumConstantsReference = new LazyFinalReference<>(() -> initEnumConstantsAtRuntime(values));
} catch (ReflectionUtilError e) {
enumConstantsReference = null;
} catch (NoClassDefFoundError e) {
String message = e.getMessage();
enumConstantsReference = new LazyFinalReference<>(() -> throwNoClassDefFoundErrorAtRuntime(message));
}
}
private static Object initEnumConstantsAtRuntime(Method values) {
try {
return values.invoke(null);
} catch (InvocationTargetException | IllegalAccessException e) {
return null;
}
}
private static Object throwNoClassDefFoundErrorAtRuntime(String message) {
throw new NoClassDefFoundError(message);
}
@Platforms(Platform.HOSTED_ONLY.class)
public void setMetaType(SharedType metaType) {
this.metaType = metaType;
}
public boolean hasDefaultMethods() {
return hasDefaultMethods;
}
public boolean declaresDefaultMethods() {
return declaresDefaultMethods;
}
public ClassInitializationInfo getClassInitializationInfo() {
return classInitializationInfo;
}
public boolean isInitialized() {
return classInitializationInfo.isInitialized();
}
public void ensureInitialized() {
EnsureClassInitializedNode.ensureClassInitialized(toClass(this));
}
public SharedType getMetaType() {
return metaType;
}
public String getSourceFileName() {
return sourceFileName;
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public int getLayoutEncoding() {
return layoutEncoding;
}
public int getTypeID() {
return typeID;
}
public short getTypeCheckSlot() {
return typeCheckSlot;
}
public short getTypeCheckStart() {
return typeCheckStart;
}
public short getTypeCheckRange() {
return typeCheckRange;
}
public int getMonitorOffset() {
return monitorOffset;
}
public DynamicHub getSuperHub() {
return superHub;
}
public DynamicHub getComponentHub() {
return componentHub;
}
public DynamicHub getArrayHub() {
return arrayHub;
}
public int getReferenceMapIndex() {
return referenceMapIndex;
}
public boolean isInstantiated() {
return isInstantiated;
}
public static DynamicHub fromClass(Class<?> clazz) {
return SubstrateUtil.cast(clazz, DynamicHub.class);
}
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static Class<?> toClass(DynamicHub hub) {
return SubstrateUtil.cast(hub, Class.class);
}
@Platforms(Platform.HOSTED_ONLY.class)
public Class<?> getHostedJavaClass() {
return hostedJavaClass;
}
@Substitute
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public String getName() {
return name;
}
public boolean isInstanceClass() {
return HubType.isInstance(hubType);
}
public boolean isReferenceInstanceClass() {
return HubType.isReferenceInstance(hubType);
}
@Substitute
private boolean isArray() {
throw VMError.shouldNotReachHere("Intrinsified in StandardGraphBuilderPlugins.");
}
public boolean hubIsArray() {
return HubType.isArray(hubType);
}
@Substitute
public boolean isInterface() {
return LayoutEncoding.isInterface(getLayoutEncoding());
}
@Substitute
public boolean isPrimitive() {
return LayoutEncoding.isPrimitive(getLayoutEncoding());
}
@Substitute
public int getModifiers() {
return modifiers;
}
@Substitute
private Object getComponentType() {
return componentHub;
}
@Substitute
private Object getSuperclass() {
return superHub;
}
@Substitute
private boolean isInstance(@SuppressWarnings("unused") Object obj) {
throw VMError.shouldNotReachHere("Intrinsified in StandardGraphBuilderPlugins.");
}
@Substitute
private Object cast(@SuppressWarnings("unused") Object obj) {
throw VMError.shouldNotReachHere("Intrinsified in StandardGraphBuilderPlugins.");
}
@Substitute
private boolean isAssignableFrom(@SuppressWarnings("unused") Class<?> cls) {
throw VMError.shouldNotReachHere("Intrinsified in StandardGraphBuilderPlugins.");
}
@Substitute
private boolean isAnnotation() {
return isInterface() && getInterfaces().length == 1 && DynamicHub.toClass(getInterfaces()[0]) == Annotation.class;
}
@Substitute
private boolean isEnum() {
return this.getSuperclass() == java.lang.Enum.class;
}
@KeepOriginal
private native Enum<?>[] getEnumConstants();
@Substitute
public Enum<?>[] getEnumConstantsShared() {
if (enumConstantsReference instanceof LazyFinalReference) {
return (Enum<?>[]) ((LazyFinalReference<?>) enumConstantsReference).get();
}
return (Enum<?>[]) enumConstantsReference;
}
@Substitute
private InputStream getResourceAsStream(String resourceName) {
final String path = resolveName(getName(), resourceName);
List<byte[]> arr = Resources.get(path);
return arr == null ? null : new ByteArrayInputStream(arr.get(0));
}
@Substitute
private URL getResource(String resourceName) {
final String path = resolveName(getName(), resourceName);
List<byte[]> arr = Resources.get(path);
return arr == null ? null : Resources.createURL(path, arr.get(0));
}
private String resolveName(String baseName, String resourceName) {
if (resourceName == null) {
return resourceName;
}
if (resourceName.startsWith("/")) {
return resourceName.substring(1);
}
int index = baseName.lastIndexOf('.');
if (index != -1) {
return baseName.substring(0, index).replace('.', '/') + "/" + resourceName;
} else {
return resourceName;
}
}
@KeepOriginal
private native ClassLoader getClassLoader();
@Substitute
private ClassLoader getClassLoader0() {
return classLoader;
}
@KeepOriginal
@TargetElement(name = "getSimpleName", onlyWith = JDK8OrEarlier.class)
private native String getSimpleNameJDK8OrEarlier();
@Substitute
@TargetElement(name = "getSimpleName", onlyWith = JDK11OrLater.class)
private String getSimpleNameJDK11OrLater() {
return getSimpleName0();
}
@KeepOriginal
@TargetElement(onlyWith = JDK11OrLater.class)
private native String getSimpleName0();
@KeepOriginal
@TargetElement(name = "getCanonicalName", onlyWith = JDK8OrEarlier.class)
private native String getCanonicalNameJDK8OrEarlier();
@SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel string comparison")
@Substitute
@TargetElement(name = "getCanonicalName", onlyWith = JDK11OrLater.class)
private String getCanonicalNameJDK11OrLater() {
String canonicalName = getCanonicalName0();
return canonicalName == Target_java_lang_Class_ReflectionData.NULL_SENTINEL ? null : canonicalName;
}
@KeepOriginal
@TargetElement(onlyWith = JDK11OrLater.class)
private native String getCanonicalName0();
@KeepOriginal
@Override
public native String getTypeName();
@KeepOriginal
@TargetElement(onlyWith = JDK8OrEarlier.class)
private static native boolean isAsciiDigit(char c);
@KeepOriginal
private native String getSimpleBinaryName();
@KeepOriginal
private native <U> Class<? extends U> asSubclass(Class<U> clazz);
@Substitute
private boolean isAnonymousClass() {
if (isAnonymousClass instanceof Boolean) {
return (Boolean) isAnonymousClass;
} else if (isAnonymousClass instanceof LinkageError) {
throw (LinkageError) isAnonymousClass;
} else if (isAnonymousClass instanceof InternalError) {
throw (InternalError) isAnonymousClass;
} else {
throw VMError.shouldNotReachHere();
}
}
@Substitute
@TargetElement(onlyWith = JDK15OrLater.class)
public boolean isHidden() {
return isHidden;
}
@Substitute
@TargetElement(onlyWith = JDK15OrLater.class)
public boolean isRecord() {
return isRecord;
}
@Substitute
private boolean isLocalClass() {
return isLocalClass;
}
@KeepOriginal
private native boolean isMemberClass();
@Substitute
public boolean isLocalOrAnonymousClass() {
return isLocalClass() || isAnonymousClass();
}
@Substitute
private Object getEnclosingClass() {
return enclosingClass;
}
@KeepOriginal
@TargetElement(name = "getDeclaringClass", onlyWith = JDK11OrLater.class)
private native Object getDeclaringClassJDK11OrLater();
@Substitute
@TargetElement(onlyWith = JDK11OrLater.class)
private Object getDeclaringClass0() {
return getDeclaringClassInternal();
}
@Substitute
@TargetElement(name = "getDeclaringClass", onlyWith = JDK8OrEarlier.class)
private Object getDeclaringClassJDK8OrEarlier() {
return getDeclaringClassInternal();
}
private Object getDeclaringClassInternal() {
if (isLocalOrAnonymousClass()) {
return null;
} else {
return enclosingClass;
}
}
@Substitute
public DynamicHub[] getInterfaces() {
return getInterfaces(this, true);
}
@Substitute
@TargetElement(onlyWith = JDK11OrLater.class)
private DynamicHub[] getInterfaces(boolean cloneArray) {
return getInterfaces(this, cloneArray);
}
private static DynamicHub[] getInterfaces(DynamicHub hub, boolean cloneArray) {
if (hub.interfacesEncoding == null) {
return new DynamicHub[0];
} else if (hub.interfacesEncoding instanceof DynamicHub) {
return new DynamicHub[]{(DynamicHub) hub.interfacesEncoding};
} else {
return cloneArray ? ((DynamicHub[]) hub.interfacesEncoding).clone() : (DynamicHub[]) hub.interfacesEncoding;
}
}
@Substitute
public Object newInstance() throws Throwable {
ensureInitialized();
final Constructor<?> nullaryConstructor = rd.nullaryConstructor;
if (nullaryConstructor == null) {
if (JavaVersionUtil.JAVA_SPEC <= 8) {
throw new InstantiationException("Type `" + this.getCanonicalNameJDK8OrEarlier() +
"` can not be instantiated reflectively as it does not have a no-parameter constructor or the no-parameter constructor has not been added explicitly to the native image.");
} else {
throw new InstantiationException("Type `" + this.getCanonicalNameJDK11OrLater() +
"` can not be instantiated reflectively as it does not have a no-parameter constructor or the no-parameter constructor has not been added explicitly to the native image.");
}
}
try {
return nullaryConstructor.newInstance((Object[]) null);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
private static Object newInstanceInstantiationError(Object instance) throws InstantiationException {
if (instance == null) {
throw VMError.shouldNotReachHere("This case should be handled by the `DynamicNewInstance` lowering.");
} else {
throw new InstantiationException("Type `" + instance.getClass().getCanonicalName() + "` can not be instantiated reflectively as it does not have a no-parameter constructor.");
}
}
private static Object newInstanceReachableError(Object instance) {
throw new RuntimeException("Constructor of `" + instance.getClass().getCanonicalName() +
"` was removed by reachability analysis. Use `Feature.BeforeAnalysisAccess.registerForReflectiveInstantiation` to register the type for reflective instantiation.");
}
@Substitute
@Override
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
return AnnotationsEncoding.decodeAnnotations(annotationsEncoding).getAnnotation(annotationClass);
}
@Substitute
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return getAnnotation(annotationClass) != null;
}
@Substitute
@Override
public Annotation[] getAnnotations() {
return AnnotationsEncoding.decodeAnnotations(annotationsEncoding).getAnnotations();
}
@Substitute
@Override
@SuppressWarnings("unchecked")
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
T[] result = getDeclaredAnnotationsByType(annotationClass);
if (result.length == 0 && DirectAnnotationAccess.isAnnotationPresent(annotationClass, Inherited.class)) {
DynamicHub superClass = (DynamicHub) this.getSuperclass();
if (superClass != null) {
result = superClass.getAnnotationsByType(annotationClass);
}
}
return result;
}
@Substitute
@Override
public Annotation[] getDeclaredAnnotations() {
return AnnotationsEncoding.decodeAnnotations(annotationsEncoding).getDeclaredAnnotations();
}
@Substitute
@Override
public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {
return GenericDeclaration.super.getDeclaredAnnotationsByType(annotationClass);
}
@Substitute
@Override
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
return AnnotationsEncoding.decodeAnnotations(annotationsEncoding).getDeclaredAnnotation(annotationClass);
}
public static final class ReflectionData {
final Field[] declaredFields;
final Field[] publicFields;
final Field[] publicUnhiddenFields;
final Method[] declaredMethods;
final Method[] publicMethods;
final Constructor<?>[] declaredConstructors;
final Constructor<?>[] publicConstructors;
final Constructor<?> nullaryConstructor;
final Field[] declaredPublicFields;
final Method[] declaredPublicMethods;
final Class<?>[] declaredClasses;
final Class<?>[] publicClasses;
final Executable enclosingMethodOrConstructor;
public ReflectionData(Field[] declaredFields, Field[] publicFields, Field[] publicUnhiddenFields, Method[] declaredMethods, Method[] publicMethods, Constructor<?>[] declaredConstructors,
Constructor<?>[] publicConstructors, Constructor<?> nullaryConstructor, Field[] declaredPublicFields, Method[] declaredPublicMethods, Class<?>[] declaredClasses,
Class<?>[] publicClasses, Executable enclosingMethodOrConstructor) {
this.declaredFields = declaredFields;
this.publicFields = publicFields;
this.publicUnhiddenFields = publicUnhiddenFields;
this.declaredMethods = declaredMethods;
this.publicMethods = publicMethods;
this.declaredConstructors = declaredConstructors;
this.publicConstructors = publicConstructors;
this.nullaryConstructor = nullaryConstructor;
this.declaredPublicFields = declaredPublicFields;
this.declaredPublicMethods = declaredPublicMethods;
this.declaredClasses = declaredClasses;
this.publicClasses = publicClasses;
this.enclosingMethodOrConstructor = enclosingMethodOrConstructor;
}
}
@TargetClass(value = java.lang.Class.class, innerClass = "MethodArray", onlyWith = JDK8OrEarlier.class)
static final class Target_java_lang_Class_MethodArray {
}
private static final ReflectionData NO_REFLECTION_DATA = 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], new Method[0], new Class<?>[0], new Class<?>[0], null);
private ReflectionData rd = NO_REFLECTION_DATA;
@Platforms(Platform.HOSTED_ONLY.class)
public void setReflectionData(ReflectionData rd) {
this.rd = rd;
}
@KeepOriginal
private native Field[] getFields();
@KeepOriginal
private native Method[] getMethods();
@KeepOriginal
private native Constructor<?>[] getConstructors();
@Substitute
private Field getField(@SuppressWarnings("hiding") String name) throws NoSuchFieldException {
for (Field field : rd.publicUnhiddenFields) {
if (field.getName().equals(name)) {
return field;
}
}
throw new NoSuchFieldException(name);
}
@Substitute
private Method getMethod(@SuppressWarnings("hiding") String name, Class<?>... parameterTypes) throws NoSuchMethodException {
Method method = searchMethods(rd.publicMethods, name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(describeMethod(getName() + "." + name + "(", parameterTypes, ")"));
}
return method;
}
@KeepOriginal
private native Constructor<?> getConstructor(Class<?>... parameterTypes);
@Substitute
private Class<?>[] getDeclaredClasses() {
return rd.declaredClasses;
}
@Substitute
private Class<?>[] getClasses() {
return rd.publicClasses;
}
@KeepOriginal
private native Field[] getDeclaredFields();
@KeepOriginal
private native Method[] getDeclaredMethods();
@KeepOriginal
private native Constructor<?>[] getDeclaredConstructors();
@KeepOriginal
private native Field getDeclaredField(@SuppressWarnings("hiding") String name);
@KeepOriginal
private native Method getDeclaredMethod(@SuppressWarnings("hiding") String name, Class<?>... parameterTypes);
@KeepOriginal
private native Constructor<?> getDeclaredConstructor(Class<?>... parameterTypes);
@Substitute
private Constructor<?>[] privateGetDeclaredConstructors(boolean publicOnly) {
return publicOnly ? rd.publicConstructors : rd.declaredConstructors;
}
@Substitute
private Field[] privateGetDeclaredFields(boolean publicOnly) {
return publicOnly ? rd.declaredPublicFields : rd.declaredFields;
}
@Substitute
private Method[] privateGetDeclaredMethods(boolean publicOnly) {
return publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
}
@Substitute
@TargetElement(name = "privateGetPublicFields", onlyWith = JDK8OrEarlier.class)
private Field[] privateGetPublicFieldsJDK8OrEarlier(@SuppressWarnings("unused") Set<Class<?>> traversedInterfaces) {
return rd.publicFields;
}
@Substitute
@TargetElement(name = "privateGetPublicFields", onlyWith = JDK11OrLater.class)
private Field[] privateGetPublicFieldsJDK11OrLater() {
return rd.publicFields;
}
@Substitute
private Method[] privateGetPublicMethods() {
return rd.publicMethods;
}
@Substitute
@TargetElement(name = "checkMemberAccess", onlyWith = JDK8OrEarlier.class)
@SuppressWarnings("unused")
private void checkMemberAccessJDK8OrEarlier(int which, Class<?> caller, boolean checkProxyInterfaces) {
}
@Substitute
@TargetElement(name = "checkMemberAccess", onlyWith = JDK11OrLater.class)
@SuppressWarnings("unused")
private void checkMemberAccessJDK11OrLater(SecurityManager sm, int which, Class<?> caller, boolean checkProxyInterfaces) {
}
@Substitute
private static Target_jdk_internal_reflect_ReflectionFactory getReflectionFactory() {
return Target_jdk_internal_reflect_ReflectionFactory.getReflectionFactory();
}
@KeepOriginal
private static native Field searchFields(Field[] fields, String name);
@KeepOriginal
private static native Method searchMethods(Method[] methods, String name, Class<?>[] parameterTypes);
@KeepOriginal
private native Constructor<?> getConstructor0(Class<?>[] parameterTypes, int which);
@KeepOriginal
private static native boolean arrayContentsEq(Object[] a1, Object[] a2);
@KeepOriginal
private static native Field[] copyFields(Field[] arg);
@KeepOriginal
private static native Method[] copyMethods(Method[] arg);
@KeepOriginal
private static native <U> Constructor<U>[] copyConstructors(Constructor<U>[] arg);
@Substitute
@TargetElement(onlyWith = JDK8OrEarlier.class)
private static String argumentTypesToString(Class<?>[] argTypes) {
return describeMethod("(", argTypes, ")");
}
@Substitute
@Override
public TypeVariable<?>[] getTypeParameters() {
return genericInfo.getTypeParameters();
}
@Substitute
public Type[] getGenericInterfaces() {
return genericInfo.hasGenericInterfaces() ? genericInfo.getGenericInterfaces() : getInterfaces();
}
@Substitute
public Type getGenericSuperclass() {
return genericInfo.hasGenericSuperClass() ? genericInfo.getGenericSuperClass() : getSuperHub();
}
@Substitute
public AnnotatedType getAnnotatedSuperclass() {
return annotatedSuperInfo.getAnnotatedSuperclass();
}
@Substitute
public AnnotatedType[] getAnnotatedInterfaces() {
return annotatedSuperInfo.getAnnotatedInterfaces();
}
@Substitute
private Method getEnclosingMethod() {
if (rd.enclosingMethodOrConstructor instanceof Method) {
return (Method) rd.enclosingMethodOrConstructor;
}
return null;
}
@Substitute
private Constructor<?> getEnclosingConstructor() {
if (rd.enclosingMethodOrConstructor instanceof Constructor) {
return (Constructor<?>) rd.enclosingMethodOrConstructor;
}
return null;
}
@Substitute
private static Class<?> forName(String className) throws ClassNotFoundException {
return ClassForNameSupport.forName(className, true);
}
@Substitute
@TargetElement(onlyWith = JDK11OrLater.class)
@SuppressWarnings({"unused"})
public static Class<?> forName(Target_java_lang_Module module, String className) {
return ClassForNameSupport.forNameOrNull(className, false);
}
@Substitute
private static Class<?> forName(String name, @SuppressWarnings("unused") boolean initialize, @SuppressWarnings("unused") ClassLoader loader) throws ClassNotFoundException {
return ClassForNameSupport.forName(name, initialize);
}
@KeepOriginal
private native Package getPackage();
@Substitute
@TargetElement(onlyWith = JDK11OrLater.class)
public String getPackageName() {
return packageNameReference.get();
}
private String computePackageName() {
String pn = null;
DynamicHub me = this;
while (me.hubIsArray()) {
me = (DynamicHub) me.getComponentType();
}
if (me.isPrimitive()) {
pn = "java.lang";
} else {
String cn = me.getName();
int dot = cn.lastIndexOf('.');
pn = (dot != -1) ? cn.substring(0, dot).intern() : "";
}
return pn;
}
@Override
@Substitute
public String toString() {
return (isInterface() ? "interface " : (isPrimitive() ? "" : "class ")) + getName();
}
@KeepOriginal
public native String toGenericString();
@KeepOriginal
public native boolean isSynthetic();
@Substitute
public Object[] getSigners() {
return null;
}
@Substitute
public ProtectionDomain getProtectionDomain() {
return allPermDomainReference.get();
}
@Substitute
public boolean desiredAssertionStatus() {
return assertionStatus;
}
@Substitute
@TargetElement(name = "getModule", onlyWith = JDK11OrLater.class)
public Target_java_lang_Module getModule() {
return (Target_java_lang_Module) module;
}
@Substitute
@TargetElement(onlyWith = JDK11OrLater.class)
public String methodToString(String nameArg, Class<?>[] argTypes) {
return describeMethod(name + "." + nameArg + "(", argTypes, ")");
}
private static String describeMethod(String prefix, Class<?>[] argTypes, String suffix) {
StringJoiner sj = new StringJoiner(", ", prefix, suffix);
if (argTypes != null) {
for (Class<?> c : argTypes) {
sj.add((c == null) ? "null" : c.getName());
}
}
return sj.toString();
}
@Substitute
private <T> Target_java_lang_Class_ReflectionData<T> reflectionData() {
throw VMError.unsupportedFeature("JDK11OrLater: DynamicHub.reflectionData()");
}
@KeepOriginal
@TargetElement(onlyWith = JDK11OrLater.class)
private native boolean isTopLevelClass();
@Substitute
@TargetElement(onlyWith = JDK11OrLater.class)
private String getSimpleBinaryName0() {
if (isAnonymousClass() || enclosingClass == null) {
return null;
}
try {
int prefix = enclosingClass.getName().length();
char firstLetter;
do {
prefix += 1;
firstLetter = name.charAt(prefix);
} while (!Character.isLetter(firstLetter));
return name.substring(prefix);
} catch (IndexOutOfBoundsException ex) {
throw new InternalError("Malformed class name", ex);
}
}
@KeepOriginal
@TargetElement(onlyWith = JDK11OrLater.class)
@SuppressWarnings({"unused"})
private native List<Method> getDeclaredPublicMethods(String nameArg, Class<?>... parameterTypes);
@Substitute
@TargetElement(onlyWith = JDK11OrLater.class)
public Class<?> getNestHost() {
return nestHost;
}
@Substitute
@TargetElement(onlyWith = JDK11OrLater.class)
public boolean isNestmateOf(Class<?> c) {
return nestHost == DynamicHub.fromClass(c).nestHost;
}
@Substitute
@TargetElement(onlyWith = JDK11OrLater.class)
private Class<?>[] getNestMembers() {
throw VMError.unsupportedFeature("Class.getNestMembers is not supported yet");
}
@Delete
private static native void registerNatives();
@Delete
static native Class<?> getPrimitiveClass(String name);
@Delete
private native Object[] getEnclosingMethod0();
@Delete
private native Class<?>[] getInterfaces0();
@Delete
native void setSigners(Object[] signers);
@Delete
private native java.security.ProtectionDomain getProtectionDomain0();
@Delete
private native String getGenericSignature0();
@Delete
native byte[] getRawAnnotations();
@Delete
native byte[] getRawTypeAnnotations();
@Delete
native Target_jdk_internal_reflect_ConstantPool getConstantPool();
@Delete
private native Field[] getDeclaredFields0(boolean publicOnly);
@Delete
private native Method[] getDeclaredMethods0(boolean publicOnly);
@Delete
private native <T> Constructor<T>[] getDeclaredConstructors0(boolean publicOnly);
@Delete
private native Class<?>[] getDeclaredClasses0();
@Delete
private static native boolean desiredAssertionStatus0(Class<?> clazz);
@Delete
@TargetElement(onlyWith = JDK8OrEarlier.class)
private native String getName0();
@Delete
@TargetElement(onlyWith = JDK11OrLater.class)
private native Class<?> getNestHost0();
@Delete
@TargetElement(onlyWith = JDK11OrLater.class)
private native Class<?>[] getNestMembers0();
@Delete
@TargetElement(onlyWith = JDK11OrLater.class)
private native String initClassName();
}
@TargetClass(className = "java.lang.Class", innerClass = "ReflectionData", onlyWith = JDK11OrLater.class)
final class Target_java_lang_Class_ReflectionData<T> {
@Alias
static String NULL_SENTINEL;
}
@TargetClass(classNameProvider = Package_jdk_internal_reflect.class, className = "ReflectionFactory")
final class Target_jdk_internal_reflect_ReflectionFactory {
@Alias
private static Target_jdk_internal_reflect_ReflectionFactory soleInstance;
@Substitute
public static Target_jdk_internal_reflect_ReflectionFactory getReflectionFactory() {
return soleInstance;
}
}
@TargetClass(classNameProvider = Package_jdk_internal_reflect.class, className = "ConstantPool")
final class Target_jdk_internal_reflect_ConstantPool {
}