Skip to content

Commit 6efd91e

Browse files
committed
Track preserved proxies
1 parent 43c0d7a commit 6efd91e

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/proxy/DynamicProxySupport.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@
3131
import java.util.regex.Pattern;
3232

3333
import org.graalvm.collections.EconomicMap;
34+
import org.graalvm.nativeimage.ImageSingletons;
3435
import org.graalvm.nativeimage.Platform;
3536
import org.graalvm.nativeimage.Platforms;
3637
import org.graalvm.nativeimage.dynamicaccess.AccessCondition;
3738
import org.graalvm.nativeimage.hosted.RuntimeClassInitialization;
38-
import org.graalvm.nativeimage.hosted.RuntimeReflection;
3939
import org.graalvm.nativeimage.impl.TypeReachabilityCondition;
40+
import org.graalvm.nativeimage.impl.RuntimeReflectionSupport;
4041

4142
import com.oracle.svm.core.configure.ConditionalRuntimeValue;
4243
import com.oracle.svm.core.configure.RuntimeConditionSet;
@@ -114,15 +115,18 @@ public synchronized void addProxyClass(AccessCondition condition, boolean preser
114115
*/
115116
Class<?>[] intfs = interfaces.clone();
116117
ProxyCacheKey key = new ProxyCacheKey(intfs);
117-
118-
if (!proxyCache.containsKey(key)) {
119-
proxyCache.put(key, new ConditionalRuntimeValue<>(RuntimeConditionSet.emptySet(preserved), createProxyClass(intfs)));
118+
ConditionalRuntimeValue<Object> conditionalValue = proxyCache.get(key);
119+
if (conditionalValue == null) {
120+
conditionalValue = new ConditionalRuntimeValue<>(RuntimeConditionSet.emptySet(preserved), createProxyClass(intfs, preserved));
121+
proxyCache.put(key, conditionalValue);
122+
} else {
123+
conditionalValue.getConditions().reportReregistered(preserved);
120124
}
121-
proxyCache.get(key).getConditions().addCondition(condition);
125+
conditionalValue.getConditions().addCondition(condition);
122126
}
123127

124128
@Platforms(Platform.HOSTED_ONLY.class)
125-
private static Object createProxyClass(Class<?>[] interfaces) {
129+
private static Object createProxyClass(Class<?>[] interfaces, boolean preserved) {
126130
try {
127131
Class<?> clazz = createProxyClassFromImplementedInterfaces(interfaces);
128132

@@ -145,14 +149,15 @@ private static Object createProxyClass(Class<?>[] interfaces) {
145149
* InvocationHandler)`, is registered for reflection so that dynamic proxy instances can
146150
* be allocated at run time.
147151
*/
148-
RuntimeReflection.register(ReflectionUtil.lookupConstructor(clazz, InvocationHandler.class));
152+
RuntimeReflectionSupport reflectionSupport = ImageSingletons.lookup(RuntimeReflectionSupport.class);
153+
reflectionSupport.register(AccessCondition.unconditional(), false, preserved, ReflectionUtil.lookupConstructor(clazz, InvocationHandler.class));
149154

150155
/*
151156
* The proxy class reflectively looks up the methods of the interfaces it implements to
152157
* pass a Method object to InvocationHandler.
153158
*/
154159
for (Class<?> intf : interfaces) {
155-
RuntimeReflection.register(intf.getMethods());
160+
reflectionSupport.register(AccessCondition.unconditional(), false, preserved, intf.getMethods());
156161
}
157162
return clazz;
158163
} catch (Throwable t) {
@@ -225,6 +230,14 @@ public Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) {
225230
return clazz;
226231
}
227232

233+
public boolean isProxyPreserved(Class<?>... interfaces) {
234+
ProxyCacheKey key = new ProxyCacheKey(interfaces);
235+
if (proxyCache.get(key) instanceof ConditionalRuntimeValue<Object> entry) {
236+
return entry.getConditions().preserved();
237+
}
238+
return false;
239+
}
240+
228241
private static RuntimeException incompatibleClassLoaders(ClassLoader provided, Class<?>[] interfaces) {
229242
StringBuilder b = new StringBuilder("Interface(s) not visible to the provided class loader: ");
230243
describeLoaderChain(b, provided);

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,9 @@ private void registerTypesForGenericSignature(Type type, int dimension) {
998998
/*
999999
* Reflection signature parsing will try to instantiate classes via Class.forName().
10001000
*/
1001-
classForNameSupport.registerClass(clazz, ClassLoaderFeature.getRuntimeClassLoader(clazz.getClassLoader()));
1001+
// GR-68706: this registration is marked as preserved to avoid clobbering "preserved"
1002+
// metadata. it should use a scoped condition once they are supported.
1003+
classForNameSupport.registerClass(AccessCondition.unconditional(), clazz, ClassLoaderFeature.getRuntimeClassLoader(clazz.getClassLoader()), true);
10021004
} else if (type instanceof TypeVariable<?>) {
10031005
/* Bounds are reified lazily. */
10041006
registerTypesForGenericSignature(queryGenericInfo(((TypeVariable<?>) type)::getBounds), dimension);

0 commit comments

Comments
 (0)