This is an automated email from the ASF dual-hosted git repository. mgrigorov pushed a commit to branch WICKET-6913-replace-cglib-with-bytebuddy in repository https://gitbox.apache.org/repos/asf/wicket.git
commit 8e1a15b3c08a59cc21c285440d1bf4d3b1876419 Author: Martin Tzvetanov Grigorov <[email protected]> AuthorDate: Tue Aug 10 01:35:07 2021 +0300 WICKET-6913 Replace CGLib with ByteBuddy in LazyInitProxyFactory TODO: Update the Objenesis related classes too and wicket-jmx --- wicket-ioc/pom.xml | 5 +- wicket-ioc/src/main/java/module-info.java | 2 +- .../apache/wicket/proxy/LazyInitProxyFactory.java | 176 ++++++++------------- .../proxy/objenesis/ObjenesisCGLibInterceptor.java | 2 +- .../proxy/objenesis/ObjenesisProxyFactory.java | 39 ++--- .../proxy/objenesis/ObjenesisProxyReplacement.java | 2 +- .../wicket/proxy/LazyInitProxyFactoryTest.java | 51 +++--- 7 files changed, 123 insertions(+), 154 deletions(-) diff --git a/wicket-ioc/pom.xml b/wicket-ioc/pom.xml index d34c07f..03688e6 100644 --- a/wicket-ioc/pom.xml +++ b/wicket-ioc/pom.xml @@ -33,8 +33,9 @@ <dependencies> <dependency> - <groupId>cglib</groupId> - <artifactId>cglib</artifactId> + <groupId>net.bytebuddy</groupId> + <artifactId>byte-buddy</artifactId> + <version>1.11.12</version> </dependency> <dependency> <groupId>javax.inject</groupId> diff --git a/wicket-ioc/src/main/java/module-info.java b/wicket-ioc/src/main/java/module-info.java index 6f7f7e1..b9814fe 100644 --- a/wicket-ioc/src/main/java/module-info.java +++ b/wicket-ioc/src/main/java/module-info.java @@ -18,7 +18,7 @@ module org.apache.wicket.ioc { requires org.apache.wicket.util; requires org.apache.wicket.core; - requires cglib; + requires net.bytebuddy; requires org.objenesis; exports org.apache.wicket.injection; diff --git a/wicket-ioc/src/main/java/org/apache/wicket/proxy/LazyInitProxyFactory.java b/wicket-ioc/src/main/java/org/apache/wicket/proxy/LazyInitProxyFactory.java index ccc7769..d478a25 100644 --- a/wicket-ioc/src/main/java/org/apache/wicket/proxy/LazyInitProxyFactory.java +++ b/wicket-ioc/src/main/java/org/apache/wicket/proxy/LazyInitProxyFactory.java @@ -22,27 +22,26 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.List; -import net.sf.cglib.core.DefaultNamingPolicy; -import net.sf.cglib.core.Predicate; -import net.sf.cglib.proxy.Callback; -import net.sf.cglib.proxy.CallbackFilter; -import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.MethodProxy; -import net.sf.cglib.proxy.NoOp; +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.NamingStrategy; +import net.bytebuddy.TypeCache; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; +import net.bytebuddy.implementation.MethodDelegation; +import net.bytebuddy.implementation.bind.annotation.AllArguments; +import net.bytebuddy.implementation.bind.annotation.Origin; +import net.bytebuddy.implementation.bind.annotation.RuntimeType; +import net.bytebuddy.matcher.ElementMatchers; import org.apache.wicket.Application; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.core.util.lang.WicketObjects; import org.apache.wicket.model.IModel; -import org.apache.wicket.proxy.objenesis.ObjenesisProxyFactory; import org.apache.wicket.util.io.IClusterable; -import org.apache.wicket.util.string.Strings; /** * A factory class that creates lazy init proxies given a type and a {@link IProxyTargetLocator} @@ -112,14 +111,19 @@ public class LazyInitProxyFactory /** * Primitive java types and their object wrappers */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - private static final List PRIMITIVES = Arrays.asList(String.class, byte.class, Byte.class, + private static final List<Class<?>> PRIMITIVES = Arrays.asList(String.class, byte.class, Byte.class, short.class, Short.class, int.class, Integer.class, long.class, Long.class, float.class, Float.class, double.class, Double.class, char.class, Character.class, boolean.class, Boolean.class); - private static final int CGLIB_CALLBACK_NO_OVERRIDE = 0; - private static final int CGLIB_CALLBACK_HANDLER = 1; + /** + * A cache used to store the dynamically generated classes by ByteBuddy. + * Without this cache a new class will be generated for each proxy creation + * and this will fill up the metaspace + */ + private static final TypeCache<TypeCache.SimpleKey> DYNAMIC_CLASS_CACHE = new TypeCache.WithInlineExpunction<>(TypeCache.Sort.SOFT); + + private static final ByteBuddy BYTE_BUDDY = new ByteBuddy().with(WicketNamingPolicy.INSTANCE); private static final boolean IS_OBJENESIS_AVAILABLE = isObjenesisAvailable(); @@ -169,26 +173,28 @@ public class LazyInitProxyFactory } else if (IS_OBJENESIS_AVAILABLE && !hasNoArgConstructor(type)) { - return ObjenesisProxyFactory.createProxy(type, locator, WicketNamingPolicy.INSTANCE); + return null; //ObjenesisProxyFactory.createProxy(type, locator, WicketNamingPolicy.INSTANCE); } else { - CGLibInterceptor handler = new CGLibInterceptor(type, locator); - - Callback[] callbacks = new Callback[2]; - callbacks[CGLIB_CALLBACK_NO_OVERRIDE] = SerializableNoOpCallback.INSTANCE; - callbacks[CGLIB_CALLBACK_HANDLER] = handler; - - Enhancer e = new Enhancer(); - e.setClassLoader(resolveClassLoader()); - e.setInterfaces(new Class[] { Serializable.class, ILazyInitProxy.class, - IWriteReplace.class }); - e.setSuperclass(type); - e.setCallbackFilter(NoOpForProtectedMethodsCGLibCallbackFilter.INSTANCE); - e.setCallbacks(callbacks); - e.setNamingPolicy(WicketNamingPolicy.INSTANCE); - - return e.create(); + ClassLoader classLoader = resolveClassLoader(); + + Class<?> dynamicType = DYNAMIC_CLASS_CACHE.findOrInsert(classLoader, + new TypeCache.SimpleKey(type), + () -> BYTE_BUDDY + .subclass(type) + .implement(Serializable.class, ILazyInitProxy.class, IWriteReplace.class) + .method(ElementMatchers.any()) + .intercept(MethodDelegation.to(new ByteBuddyInterceptor(type, locator))) + .make() + .load(classLoader, ClassLoadingStrategy.Default.INJECTION) + .getLoaded()); + + try { + return dynamicType.getDeclaredConstructor().newInstance(); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new WicketRuntimeException(e); + } } } @@ -286,15 +292,13 @@ public class LazyInitProxyFactory } /** - * Method interceptor for proxies representing concrete object not backed by an interface. These - * proxies are represented by cglib proxies. + * Method interceptor for proxies representing concrete object not backed by an interface. + * These proxies are represented by ByteBuddy proxies. * * @author Igor Vaynberg (ivaynberg) - * */ - public abstract static class AbstractCGLibInterceptor + public abstract static class AbstractByteBuddyInterceptor implements - MethodInterceptor, ILazyInitProxy, Serializable, IWriteReplace @@ -316,20 +320,17 @@ public class LazyInitProxyFactory * @param locator * object locator used to locate the object this proxy represents */ - public AbstractCGLibInterceptor(final Class<?> type, final IProxyTargetLocator locator) + public AbstractByteBuddyInterceptor(final Class<?> type, final IProxyTargetLocator locator) { super(); typeName = type.getName(); this.locator = locator; } - /** - * @see net.sf.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, - * java.lang.reflect.Method, java.lang.Object[], net.sf.cglib.proxy.MethodProxy) - */ - @Override - public Object intercept(final Object object, final Method method, final Object[] args, - final MethodProxy proxy) throws Throwable + @RuntimeType + public Object intercept(final @Origin Method method, + final @AllArguments Object[] args) + throws Throwable { if (isFinalizeMethod(method)) { @@ -361,12 +362,10 @@ public class LazyInitProxyFactory { target = locator.locateProxyTarget(); } - return proxy.invoke(target, args); + + return method.invoke(target, args); } - /** - * @see org.apache.wicket.proxy.ILazyInitProxy#getObjectLocator() - */ @Override public IProxyTargetLocator getObjectLocator() { @@ -375,21 +374,18 @@ public class LazyInitProxyFactory } /** - * Method interceptor for proxies representing concrete object not backed by an interface. These - * proxies are representing by cglib proxies. + * Method interceptor for proxies representing concrete object not backed by an interface. + * These proxies are representing by ByteBuddy proxies. * * @author Igor Vaynberg (ivaynberg) */ - protected static class CGLibInterceptor extends AbstractCGLibInterceptor + protected static class ByteBuddyInterceptor extends AbstractByteBuddyInterceptor { - public CGLibInterceptor(Class<?> type, IProxyTargetLocator locator) + public ByteBuddyInterceptor(Class<?> type, IProxyTargetLocator locator) { super(type, locator); } - /** - * @see org.apache.wicket.proxy.LazyInitProxyFactory.IWriteReplace#writeReplace() - */ @Override public Object writeReplace() throws ObjectStreamException { @@ -398,47 +394,6 @@ public class LazyInitProxyFactory } /** - * Serializable implementation of the NoOp callback. - */ - public static class SerializableNoOpCallback implements NoOp, Serializable - { - private static final long serialVersionUID = 1L; - - private static final NoOp INSTANCE = new SerializableNoOpCallback(); - } - - /** - * CGLib callback filter which does not intercept protected methods. - * - * Protected methods need to be called with invokeSuper() instead of invoke(). - * When invoke() is called on a protected method, it throws an "IllegalArgumentException: - * Protected method" exception. - * That being said, we do not need to intercept the protected methods so this callback filter - * is designed to use a NoOp callback for protected methods. - * - * @see <a href="http://comments.gmane.org/gmane.comp.java.cglib.devel/720">Discussion about - * this very issue in Spring AOP</a> - * @see <a href="https://github.com/wicketstuff/core/wiki/SpringReference">The WicketStuff - * SpringReference project which worked around this issue</a> - */ - private static class NoOpForProtectedMethodsCGLibCallbackFilter implements CallbackFilter - { - private static final CallbackFilter INSTANCE = new NoOpForProtectedMethodsCGLibCallbackFilter(); - - @Override - public int accept(Method method) { - if (Modifier.isProtected(method.getModifiers())) - { - return CGLIB_CALLBACK_NO_OVERRIDE; - } - else - { - return CGLIB_CALLBACK_HANDLER; - } - } - } - - /** * Invocation handler for proxies representing interface based object. For interface backed * objects dynamic jdk proxies are used. * @@ -526,18 +481,12 @@ public class LazyInitProxyFactory } } - /** - * @see org.apache.wicket.proxy.ILazyInitProxy#getObjectLocator() - */ @Override public IProxyTargetLocator getObjectLocator() { return locator; } - /** - * @see org.apache.wicket.proxy.LazyInitProxyFactory.IWriteReplace#writeReplace() - */ @Override public Object writeReplace() throws ObjectStreamException { @@ -611,7 +560,7 @@ public class LazyInitProxyFactory (method.getParameterTypes().length == 0) && method.getName().equals("writeReplace"); } - public static final class WicketNamingPolicy extends DefaultNamingPolicy + public static final class WicketNamingPolicy extends NamingStrategy.AbstractBase { public static final WicketNamingPolicy INSTANCE = new WicketNamingPolicy(); @@ -621,14 +570,23 @@ public class LazyInitProxyFactory } @Override - public String getClassName(final String prefix, final String source, final Object key, - final Predicate names) - { + protected String name(TypeDescription superClass) { + final String prefix = superClass.getName(); int lastIdxOfDot = prefix.lastIndexOf('.'); String packageName = prefix.substring(0, lastIdxOfDot); String className = prefix.substring(lastIdxOfDot + 1); - String newPrefix = packageName + ".Wicket_Proxy_" + className; - return super.getClassName(newPrefix, source, key, names); + String name = packageName + ".Wicket_Proxy_" + className; + return name; + } + + @Override + public String redefine(TypeDescription typeDescription) { + return typeDescription.getName(); + } + + @Override + public String rebase(TypeDescription typeDescription) { + return typeDescription.getName(); } } diff --git a/wicket-ioc/src/main/java/org/apache/wicket/proxy/objenesis/ObjenesisCGLibInterceptor.java b/wicket-ioc/src/main/java/org/apache/wicket/proxy/objenesis/ObjenesisCGLibInterceptor.java index 63975a0..b4197ea 100644 --- a/wicket-ioc/src/main/java/org/apache/wicket/proxy/objenesis/ObjenesisCGLibInterceptor.java +++ b/wicket-ioc/src/main/java/org/apache/wicket/proxy/objenesis/ObjenesisCGLibInterceptor.java @@ -25,7 +25,7 @@ import org.apache.wicket.proxy.LazyInitProxyFactory; * Method interceptor for proxies representing concrete object not backed by an interface. These * proxies are representing by cglib proxies. */ -public class ObjenesisCGLibInterceptor extends LazyInitProxyFactory.AbstractCGLibInterceptor +public class ObjenesisCGLibInterceptor extends LazyInitProxyFactory.AbstractByteBuddyInterceptor { public ObjenesisCGLibInterceptor(Class<?> type, IProxyTargetLocator locator) { super(type, locator); diff --git a/wicket-ioc/src/main/java/org/apache/wicket/proxy/objenesis/ObjenesisProxyFactory.java b/wicket-ioc/src/main/java/org/apache/wicket/proxy/objenesis/ObjenesisProxyFactory.java index 730da6b..2be6129 100644 --- a/wicket-ioc/src/main/java/org/apache/wicket/proxy/objenesis/ObjenesisProxyFactory.java +++ b/wicket-ioc/src/main/java/org/apache/wicket/proxy/objenesis/ObjenesisProxyFactory.java @@ -18,36 +18,39 @@ package org.apache.wicket.proxy.objenesis; import java.io.Serializable; +import javax.security.auth.callback.Callback; + import org.apache.wicket.proxy.ILazyInitProxy; import org.apache.wicket.proxy.IProxyTargetLocator; import org.apache.wicket.proxy.LazyInitProxyFactory.IWriteReplace; import org.objenesis.ObjenesisStd; -import net.sf.cglib.core.NamingPolicy; -import net.sf.cglib.proxy.Callback; -import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.proxy.Factory; +//import net.sf.cglib.core.NamingPolicy; +//import net.sf.cglib.proxy.Callback; +//import net.sf.cglib.proxy.Enhancer; +//import net.sf.cglib.proxy.Factory; public class ObjenesisProxyFactory { private static final ObjenesisStd OBJENESIS = new ObjenesisStd(false); - public static Object createProxy(final Class<?> type, final IProxyTargetLocator locator, NamingPolicy namingPolicy) + public static Object createProxy(final Class<?> type, final IProxyTargetLocator locator/*, NamingPolicy namingPolicy*/) { ObjenesisCGLibInterceptor handler = new ObjenesisCGLibInterceptor(type, locator); - Enhancer e = new Enhancer(); - e.setInterfaces(new Class[]{Serializable.class, ILazyInitProxy.class, IWriteReplace.class}); - e.setSuperclass(type); - e.setCallbackType(handler.getClass()); - e.setNamingPolicy(namingPolicy); - Class<?> proxyClass = e.createClass(); - - Object instance = OBJENESIS.newInstance(proxyClass); - - // set callbacks directly (WICKET-6607) - ((Factory) instance).setCallbacks(new Callback[]{handler}); - - return instance; +// Enhancer e = new Enhancer(); +// e.setInterfaces(new Class[]{Serializable.class, ILazyInitProxy.class, IWriteReplace.class}); +// e.setSuperclass(type); +// e.setCallbackType(handler.getClass()); +// e.setNamingPolicy(namingPolicy); +// Class<?> proxyClass = e.createClass(); +// +// Object instance = OBJENESIS.newInstance(proxyClass); +// +// // set callbacks directly (WICKET-6607) +// ((Factory) instance).setCallbacks(new Callback[]{handler}); +// +// return instance; + return null; } } diff --git a/wicket-ioc/src/main/java/org/apache/wicket/proxy/objenesis/ObjenesisProxyReplacement.java b/wicket-ioc/src/main/java/org/apache/wicket/proxy/objenesis/ObjenesisProxyReplacement.java index cbffee8..7d2dc1d 100644 --- a/wicket-ioc/src/main/java/org/apache/wicket/proxy/objenesis/ObjenesisProxyReplacement.java +++ b/wicket-ioc/src/main/java/org/apache/wicket/proxy/objenesis/ObjenesisProxyReplacement.java @@ -50,6 +50,6 @@ class ObjenesisProxyReplacement implements IClusterable "] with the currently configured org.apache.wicket.application.IClassResolver"); throw new WicketRuntimeException(cause); } - return ObjenesisProxyFactory.createProxy(clazz, locator, LazyInitProxyFactory.WicketNamingPolicy.INSTANCE); + return ObjenesisProxyFactory.createProxy(clazz, locator/*, LazyInitProxyFactory.WicketNamingPolicy.INSTANCE*/); } } diff --git a/wicket-ioc/src/test/java/org/apache/wicket/proxy/LazyInitProxyFactoryTest.java b/wicket-ioc/src/test/java/org/apache/wicket/proxy/LazyInitProxyFactoryTest.java index 5483ce4..6b907d2 100644 --- a/wicket-ioc/src/test/java/org/apache/wicket/proxy/LazyInitProxyFactoryTest.java +++ b/wicket-ioc/src/test/java/org/apache/wicket/proxy/LazyInitProxyFactoryTest.java @@ -25,6 +25,7 @@ import org.apache.wicket.proxy.util.InterfaceObject; import org.apache.wicket.proxy.util.ObjectMethodTester; import org.junit.jupiter.api.Test; +import java.io.ObjectStreamException; import java.lang.reflect.Proxy; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -39,11 +40,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; * @author Igor Vaynberg (ivaynberg) * */ -public class LazyInitProxyFactoryTest +class LazyInitProxyFactoryTest { private static InterfaceObject interfaceObject = new InterfaceObject("interface"); - private static ConcreteObject concreteObject = new ConcreteObject("concrete"); + private static final ConcreteObject concreteObject = new ConcreteObject("concrete"); private static final PackagePrivateConcreteObject PACKAGE_PRIVATE_CONCRETE_OBJECT = new PackagePrivateConcreteObject("package-private-concrete"); @@ -58,7 +59,7 @@ public class LazyInitProxyFactoryTest } }; - private static IProxyTargetLocator concreteObjectLocator = new IProxyTargetLocator() + private static final IProxyTargetLocator concreteObjectLocator = new IProxyTargetLocator() { private static final long serialVersionUID = 1L; @@ -67,6 +68,11 @@ public class LazyInitProxyFactoryTest { return LazyInitProxyFactoryTest.concreteObject; } + + // This method is needed to prevent (de)serialization of this locator instance in #testByteBuddyInterceptorReplacement() + private Object readResolve() throws ObjectStreamException { + return concreteObjectLocator; + } }; private final static IProxyTargetLocator PACKAGE_PRIVATE_CONCRETE_OBJECT_LOCATOR = new IProxyTargetLocator() @@ -95,7 +101,7 @@ public class LazyInitProxyFactoryTest * Tests lazy init proxy to represent interfaces */ @Test - public void testInterfaceProxy() + void testInterfaceProxy() { // test proxy creation for an interface class IInterface proxy = (IInterface)LazyInitProxyFactory.createProxy(IInterface.class, @@ -106,15 +112,15 @@ public class LazyInitProxyFactoryTest // test proxy implements ILazyInitProxy assertTrue(proxy instanceof ILazyInitProxy); - assertTrue(((ILazyInitProxy)proxy).getObjectLocator() == interfaceObjectLocator); + assertSame(((ILazyInitProxy) proxy).getObjectLocator(), interfaceObjectLocator); // test method invocation - assertEquals(proxy.getMessage(), "interface"); + assertEquals("interface", proxy.getMessage()); // test serialization IInterface proxy2 = WicketObjects.cloneObject(proxy); - assertTrue(proxy != proxy2); - assertEquals(proxy2.getMessage(), "interface"); + assertNotSame(proxy, proxy2); + assertEquals("interface", proxy2.getMessage()); // test equals/hashcode method interception final IObjectMethodTester tester = new ObjectMethodTester(); @@ -143,32 +149,33 @@ public class LazyInitProxyFactoryTest * Tests lazy init proxy to represent concrete objects */ @Test - public void testConcreteProxy() + void testConcreteProxy() { ConcreteObject proxy = (ConcreteObject)LazyInitProxyFactory.createProxy( ConcreteObject.class, concreteObjectLocator); // test proxy implements ILazyInitProxy assertTrue(proxy instanceof ILazyInitProxy); - assertSame(((ILazyInitProxy) proxy).getObjectLocator(), concreteObjectLocator); + final IProxyTargetLocator objectLocator = ((ILazyInitProxy) proxy).getObjectLocator(); + assertSame(objectLocator, concreteObjectLocator); // test we do not have a jdk dynamic proxy assertFalse(Proxy.isProxyClass(proxy.getClass())); // test method invocation - assertEquals(proxy.getMessage(), "concrete"); + assertEquals("concrete", proxy.getMessage()); // test serialization ConcreteObject proxy2 = WicketObjects.cloneObject(proxy); assertNotSame(proxy, proxy2); - assertEquals(proxy2.getMessage(), "concrete"); + assertEquals("concrete", proxy2.getMessage()); // test equals/hashcode method interception final IObjectMethodTester tester = new ObjectMethodTester(); assertTrue(tester.isValid()); // test only a single class is generated, - // otherwise permgen space will fill up with each proxy + // otherwise meta space will fill up with each proxy assertSame(proxy.getClass(), LazyInitProxyFactory.createProxy( ConcreteObject.class, concreteObjectLocator).getClass()); @@ -197,25 +204,25 @@ public class LazyInitProxyFactoryTest * https://issues.apache.org/jira/browse/WICKET-4324 */ @Test - public void testPackagePrivateConcreteProxy() + void testPackagePrivateConcreteProxy() { PackagePrivateConcreteObject proxy = (PackagePrivateConcreteObject)LazyInitProxyFactory.createProxy( PackagePrivateConcreteObject.class, PACKAGE_PRIVATE_CONCRETE_OBJECT_LOCATOR); // test proxy implements ILazyInitProxy assertTrue(proxy instanceof ILazyInitProxy); - assertTrue(((ILazyInitProxy)proxy).getObjectLocator() == PACKAGE_PRIVATE_CONCRETE_OBJECT_LOCATOR); + assertSame(((ILazyInitProxy)proxy).getObjectLocator(), PACKAGE_PRIVATE_CONCRETE_OBJECT_LOCATOR); // test we do not have a jdk dynamic proxy assertFalse(Proxy.isProxyClass(proxy.getClass())); // test method invocation - assertEquals(proxy.getMessage(), "package-private-concrete"); + assertEquals("package-private-concrete", proxy.getMessage()); // test serialization PackagePrivateConcreteObject proxy2 = WicketObjects.cloneObject(proxy); - assertTrue(proxy != proxy2); - assertEquals(proxy2.getMessage(), "package-private-concrete"); + assertNotSame(proxy, proxy2); + assertEquals("package-private-concrete", proxy2.getMessage()); // test equals/hashcode method interception final IObjectMethodTester tester = new ObjectMethodTester(); @@ -246,23 +253,23 @@ public class LazyInitProxyFactoryTest } /** - * Tests lazy init concrete replacement replacement + * Tests lazy init concrete replacement */ @Test - public void testCGLibInterceptorReplacement() + void testByteBuddyInterceptorReplacement() { ProxyReplacement ser = new ProxyReplacement(ConcreteObject.class.getName(), concreteObjectLocator); Object proxy2 = WicketObjects.cloneObject(ser); - assertEquals(((ConcreteObject)proxy2).getMessage(), "concrete"); + assertEquals("concrete", ((ConcreteObject)proxy2).getMessage()); } /** * Tests String beans. */ @Test - public void testStringProxy() + void testStringProxy() { // We special-case String objects to avoid proxying them, as they're // final.
