3131import java .util .regex .Pattern ;
3232
3333import org .graalvm .collections .EconomicMap ;
34+ import org .graalvm .nativeimage .ImageSingletons ;
3435import org .graalvm .nativeimage .Platform ;
3536import org .graalvm .nativeimage .Platforms ;
3637import org .graalvm .nativeimage .dynamicaccess .AccessCondition ;
3738import org .graalvm .nativeimage .hosted .RuntimeClassInitialization ;
38- import org .graalvm .nativeimage .hosted .RuntimeReflection ;
3939import org .graalvm .nativeimage .impl .TypeReachabilityCondition ;
40+ import org .graalvm .nativeimage .impl .RuntimeReflectionSupport ;
4041
4142import com .oracle .svm .core .configure .ConditionalRuntimeValue ;
4243import 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 );
0 commit comments