diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java index b9d1f9da589d..3a58b13efd97 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java @@ -240,14 +240,10 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ private DynamicHub arrayHub; /** - * The hub for the enclosing class, or null if no enclosing class. - *
- * The value is lazily initialized to break cycles. But it is initialized during static
- * analysis, so we do not have to annotate is as an {@link UnknownObjectField}.
- *
- * @see Class#getEnclosingClass()
+ * The class that declares this class, as returned by {@code Class.getDeclaringClass0} or an
+ * exception that happened at image-build time.
*/
- private DynamicHub enclosingClass;
+ private final Object declaringClass;
/**
* The interfaces that this class implements. Either null (no interfaces), a {@link DynamicHub}
@@ -351,7 +347,7 @@ public void setModule(Module module) {
@Platforms(Platform.HOSTED_ONLY.class)
public DynamicHub(Class> hostedJavaClass, String name, HubType hubType, ReferenceType referenceType, Object isLocalClass, Object isAnonymousClass, DynamicHub superType, DynamicHub componentHub,
String sourceFileName, int modifiers, ClassLoader classLoader, boolean isHidden, boolean isRecord, Class> nestHost, boolean assertionStatus,
- boolean hasDefaultMethods, boolean declaresDefaultMethods, boolean isSealed, String simpleBinaryName) {
+ boolean hasDefaultMethods, boolean declaresDefaultMethods, boolean isSealed, String simpleBinaryName, Object declaringClass) {
this.hostedJavaClass = hostedJavaClass;
this.name = name;
this.hubType = hubType.getValue();
@@ -364,6 +360,7 @@ public DynamicHub(Class> hostedJavaClass, String name, HubType hubType, Refere
this.modifiers = modifiers;
this.nestHost = nestHost;
this.simpleBinaryName = simpleBinaryName;
+ this.declaringClass = declaringClass;
this.flags = NumUtil.safeToUByte(makeFlag(IS_PRIMITIVE_FLAG_BIT, hostedJavaClass.isPrimitive()) |
makeFlag(IS_INTERFACE_FLAG_BIT, hostedJavaClass.isInterface()) |
@@ -422,12 +419,6 @@ public void setArrayHub(DynamicHub arrayHub) {
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 setInterfacesEncoding(Object interfacesEncoding) {
this.interfacesEncoding = interfacesEncoding;
@@ -823,25 +814,23 @@ public boolean isLocalOrAnonymousClass() {
return isLocalClass() || isAnonymousClass();
}
- @Substitute
- private Object getEnclosingClass() {
- PredefinedClassesSupport.throwIfUnresolvable(toClass(enclosingClass), getClassLoader0());
- return enclosingClass;
- }
+ @KeepOriginal
+ private native Class> getEnclosingClass();
@KeepOriginal
- private native Object getDeclaringClass();
+ private native Class> getDeclaringClass();
@Substitute
- private Object getDeclaringClass0() {
- return getDeclaringClassInternal();
- }
-
- private Object getDeclaringClassInternal() {
- if (isLocalOrAnonymousClass()) {
+ private Class> getDeclaringClass0() {
+ if (declaringClass == null) {
return null;
+ } else if (declaringClass instanceof Class) {
+ PredefinedClassesSupport.throwIfUnresolvable((Class>) declaringClass, getClassLoader0());
+ return (Class>) declaringClass;
+ } else if (declaringClass instanceof LinkageError) {
+ throw (LinkageError) declaringClass;
} else {
- return getEnclosingClass();
+ throw VMError.shouldNotReachHere();
}
}
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java
index aacb4e4b46ce..1d3d76935767 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java
@@ -395,7 +395,7 @@ private DynamicHub createHub(AnalysisType type) {
final DynamicHub dynamicHub = new DynamicHub(javaClass, className, computeHubType(type), computeReferenceType(type),
isLocalClass(javaClass), isAnonymousClass(javaClass), superHub, componentHub, sourceFileName,
modifiers, hubClassLoader, isHidden, isRecord, nestHost, assertionStatus, type.hasDefaultMethods(),
- type.declaresDefaultMethods(), isSealed, simpleBinaryName);
+ type.declaresDefaultMethods(), isSealed, simpleBinaryName, getDeclaringClass(javaClass));
ModuleAccess.extractAndSetModule(dynamicHub, javaClass);
return dynamicHub;
}
@@ -406,11 +406,7 @@ private Object isLocalClass(Class> javaClass) {
} catch (InternalError e) {
return e;
} catch (LinkageError e) {
- if (!linkAtBuildTimeSupport.linkAtBuildTime(javaClass)) {
- return e;
- } else {
- return unsupportedMethod(javaClass, "isLocalClass");
- }
+ return handleLinkageError(javaClass, "isLocalClass", e);
}
}
@@ -424,18 +420,32 @@ private Object isAnonymousClass(Class> javaClass) {
} catch (InternalError e) {
return e;
} catch (LinkageError e) {
- if (!linkAtBuildTimeSupport.linkAtBuildTime(javaClass)) {
- return e;
- } else {
- return unsupportedMethod(javaClass, "isAnonymousClass");
+ return handleLinkageError(javaClass, "isAnonymousClass", e);
+ }
+ }
+
+ private final Method getDeclaringClass0 = ReflectionUtil.lookupMethod(Class.class, "getDeclaringClass0");
+
+ private Object getDeclaringClass(Class> javaClass) {
+ try {
+ return getDeclaringClass0.invoke(javaClass);
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof LinkageError) {
+ return handleLinkageError(javaClass, getDeclaringClass0.getName(), (LinkageError) e.getCause());
}
+ throw VMError.shouldNotReachHere(e);
+ } catch (IllegalAccessException e) {
+ throw VMError.shouldNotReachHere(e);
}
}
- private Object unsupportedMethod(Class> javaClass, String methodName) {
+ private LinkageError handleLinkageError(Class> javaClass, String methodName, LinkageError linkageError) {
+ if (!linkAtBuildTimeSupport.linkAtBuildTime(javaClass)) {
+ return linkageError; /* It's rethrown at run time. */
+ }
String message = "Discovered a type for which " + methodName + " cannot be called: " + javaClass.getTypeName() + ". " +
linkAtBuildTimeSupport.errorMessageFor(javaClass);
- throw new UnsupportedFeatureException(message);
+ throw new UnsupportedFeatureException(message, linkageError);
}
private final Method getSimpleBinaryName0 = ReflectionUtil.lookupMethod(Class.class, "getSimpleBinaryName0");
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java
index fd03b8f4021c..0f902c93fb81 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java
@@ -36,8 +36,6 @@
import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.ObjectScanner.OtherReason;
-import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException;
-import com.oracle.graal.pointsto.constraints.UnsupportedFeatures;
import com.oracle.graal.pointsto.heap.ImageHeapScanner;
import com.oracle.graal.pointsto.meta.AnalysisField;
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
@@ -61,14 +59,12 @@ public class DynamicHubInitializer {
private final BigBang bb;
private final SVMHost hostVM;
private final AnalysisMetaAccess metaAccess;
- private final UnsupportedFeatures unsupportedFeatures;
private final ConstantReflectionProvider constantReflection;
private final Map