[ 
https://issues.apache.org/jira/browse/WICKET-7204?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18112971#comment-18112971
 ] 

ASF GitHub Bot commented on WICKET-7204:
----------------------------------------

papegaaij commented on code in PR #1577:
URL: https://github.com/apache/wicket/pull/1577#discussion_r3961475632


##########
wicket-ioc/src/main/java/org/apache/wicket/proxy/bytebuddy/ByteBuddyProxyFactory.java:
##########
@@ -17,8 +17,10 @@
 package org.apache.wicket.proxy.bytebuddy;
 
 import java.io.Serializable;
+import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;

Review Comment:
   `Modifier` is not needed once the branch is on the package rather than on 
the visibility.
   
   ```suggestion
   ```



##########
wicket-ioc/src/main/java/org/apache/wicket/proxy/bytebuddy/ByteBuddyProxyFactory.java:
##########
@@ -116,10 +120,26 @@ public static <T> Class<T> createOrGetProxyClass(Class<T> 
type)
                                                
.implement(InterceptorMutator.class).intercept(FieldAccessor.ofBeanProperty())
                                                .implement(Serializable.class, 
IWriteReplace.class, 
ILazyInitProxy.class).intercept(MethodDelegation.toField(INTERCEPTOR_FIELD_NAME))
                                                .make()
-                                               .load(classLoader, 
ClassLoadingStrategy.Default.INJECTION.allowExistingTypes())
+                                               .load(classLoader, 
loadingStrategy)
                                                .getLoaded());

Review Comment:
   The monitor argument makes class creation for one `(loader, type)` pair 
mutually exclusive. Without it, `UsingLookup` has no `allowExistingTypes()` 
equivalent and concurrent first use of a package-private type defines the class 
twice — WICKET-7005 again.
   
   ```suggestion
                                                .load(classLoader, 
resolveLoadingStrategy(type))
                                                .getLoaded(),
                                DYNAMIC_CLASS_CACHE);
   ```



##########
wicket-ioc/src/main/java/org/apache/wicket/proxy/bytebuddy/ByteBuddyProxyFactory.java:
##########
@@ -100,8 +102,10 @@ public <T> T createProxy(final Class<T> type, final 
IProxyTargetLocator locator)
 
        @SuppressWarnings("unchecked")
        public static <T> Class<T> createOrGetProxyClass(Class<T> type)
-       {
+       {               
+               ClassLoadingStrategy<ClassLoader> loadingStrategy = 
resolveLoadingStrategy(type);
                ClassLoader classLoader = resolveClassLoader();
+               

Review Comment:
   Resolving the strategy here runs `privateLookupIn` on every `createProxy` 
call, not just on a cache miss, and makes it throw even when the proxy class is 
already cached. Moving it into the lambda also lets the trailing whitespace go.
   
   ```suggestion
        {
                ClassLoader classLoader = resolveClassLoader();
   
   ```



##########
wicket-ioc/src/main/java/org/apache/wicket/proxy/bytebuddy/ByteBuddyProxyFactory.java:
##########
@@ -205,7 +225,9 @@ private static boolean hasNoArgConstructor(Class<?> type)
                for (Constructor<?> constructor : 
type.getDeclaredConstructors())
                {
                        if (constructor.getParameterTypes().length == 0)
+                       {

Review Comment:
   Unrelated to the fix — worth dropping to keep the commit to one thing.



##########
wicket-ioc/src/main/java/org/apache/wicket/proxy/bytebuddy/ByteBuddyProxyFactory.java:
##########
@@ -116,10 +120,26 @@ public static <T> Class<T> createOrGetProxyClass(Class<T> 
type)
                                                
.implement(InterceptorMutator.class).intercept(FieldAccessor.ofBeanProperty())
                                                .implement(Serializable.class, 
IWriteReplace.class, 
ILazyInitProxy.class).intercept(MethodDelegation.toField(INTERCEPTOR_FIELD_NAME))
                                                .make()
-                                               .load(classLoader, 
ClassLoadingStrategy.Default.INJECTION.allowExistingTypes())
+                                               .load(classLoader, 
loadingStrategy)
                                                .getLoaded());
        }
 
+       private static ClassLoadingStrategy<ClassLoader> 
resolveLoadingStrategy(Class<?> type) 
+       {
+               try 
+               {
+                       int modifiers = type.getModifiers();
+                       
+                       return Modifier.isPublic(modifiers)
+                                  ? 
ClassLoadingStrategy.Default.WRAPPER.allowExistingTypes()
+                                  : 
ClassLoadingStrategy.UsingLookup.of(MethodHandles.privateLookupIn(type, 
MethodHandles.lookup()));
+               } 
+               catch (IllegalAccessException e) 
+               {
+                       throw new WicketRuntimeException(e);
+               }
+       }

Review Comment:
   This is the core of it: branch on whether the proxy keeps the type's 
package, not on the type's visibility. Only a `java.*` proxy is renamed into 
another package by `WicketNamingStrategy`, and that is the only case that needs 
a class loader of its own — `privateLookupIn` cannot serve it anyway, since 
`java.base` does not open its packages.
   
   The message on the exception matters here: when it fires, it is because a 
named module does not `open` its package to wicket-ioc, and a bare 
`IllegalAccessException` gives the user nothing to act on.
   
   ```suggestion
        /**
         * The proxy has to be defined in the same runtime package as the type 
it proxies, or the
         * package private methods it overrides are not overridden at all. Only 
a proxy for a
         * <em>java.**</em> type is renamed into another package, and needs a 
class loader of its own.
         */
        private static ClassLoadingStrategy<ClassLoader> 
resolveLoadingStrategy(Class<?> type)
        {
                if (type.getName().startsWith("java."))
                {
                        return 
ClassLoadingStrategy.Default.WRAPPER.allowExistingTypes();
                }
   
                try
                {
                        return ClassLoadingStrategy.UsingLookup
                                .of(MethodHandles.privateLookupIn(type, 
MethodHandles.lookup()));
                }
                catch (IllegalAccessException e)
                {
                        throw new WicketRuntimeException("Cannot create a proxy 
for " + type.getName()
                                + ", because its package is not open to " + 
ByteBuddyProxyFactory.class.getModule(), e);
                }
        }
   ```



##########
pom.xml:
##########
@@ -159,7 +159,7 @@
                <aspectj.version>1.9.25.1</aspectj.version>
                <assertj-core.version>3.27.7</assertj-core.version>
                <bouncycastle.version>1.85.2</bouncycastle.version>
-               <byte-buddy.version>1.18.8</byte-buddy.version>
+               <byte-buddy.version>1.18.13</byte-buddy.version>

Review Comment:
   This bump is separable from the fix: 1.18.13 does not disable `INJECTION` (I 
checked on JDK 25), so it is not what forces the change. No objection to 
bumping, but it reads as part of the fix here.





> Don't use INJECTION for ByteBuddy proxy creation 
> -------------------------------------------------
>
>                 Key: WICKET-7204
>                 URL: https://issues.apache.org/jira/browse/WICKET-7204
>             Project: Wicket
>          Issue Type: Improvement
>            Reporter: Andrea Del Bene
>            Assignee: Andrea Del Bene
>            Priority: Major
>             Fix For: 11.0.0
>
>
> The current proxy creation with byte buddy uses 
> ClassLoadingStrategy.Default.INJECTION. ad class loading strategy, but this 
> relies on Java Unsafe support, which is deprecated and disabled with the 
> newer release of ByteBuddy



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to