You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2021/08/12 11:07:35 UTC

[wicket] 01/03: WICKET-6913 Replace CGLib with ByteBuddy in LazyInitProxyFactory

This is an automated email from the ASF dual-hosted git repository.

mgrigorov pushed a commit to branch WICKET-6913-replace-cglib-with-bytebuddy-wicket-10.x
in repository https://gitbox.apache.org/repos/asf/wicket.git

commit 44b9755a0cb8dbc909523c7e123cbf24c8381cf3
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
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
    (cherry picked from commit 8e1a15b3c08a59cc21c285440d1bf4d3b1876419)
---
 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 a7da8d9..1a43586 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>jakarta.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.