/** * Performs a benchmark of an interface implementation using cglib. * * @return The created instance, in order to avoid JIT removal. */ @Benchmark public ExampleInterface benchmarkCglib() { Enhancer enhancer = new Enhancer(); enhancer.setUseCache(false); enhancer.setClassLoader(newClassLoader()); enhancer.setSuperclass(baseClass); CallbackHelper callbackHelper = new CallbackHelper(Object.class, new Class[] {baseClass}) { @Override protected Object getCallback(Method method) { if (method.getDeclaringClass() == baseClass) { return new FixedValue() { @Override public Object loadObject() throws Exception { return null; } }; } else { return NoOp.INSTANCE; } } }; enhancer.setCallbackFilter(callbackHelper); enhancer.setCallbacks(callbackHelper.getCallbacks()); return (ExampleInterface) enhancer.create(); }
@SuppressWarnings("unchecked") public List<Class<? extends ModuleProvider<?>>> getModuleClasses() { List<Class<? extends ModuleProvider<?>>> out = new ArrayList<Class<? extends ModuleProvider<?>>>(); for (int i = 0; i < 10; i++) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(NullModule.class); enhancer.setClassLoader(this.getClass().getClassLoader()); enhancer.setCallbackTypes(new Class[] {Callback1.class}); enhancer.setSerialVersionUID(new Long(i)); enhancer.setInterfaces(new Class[] {Module.class}); out.add(enhancer.createClass()); } return out; }
@Override public <T extends PropertyContainer> Object createProxy( T container, TypeWrapper<T> wrapper, Class<?> instanceClass) { CglibEntityInterceptor<T> interceptor = new CglibEntityInterceptor<T>(container, wrapper); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(instanceClass); enhancer.setInterfaces(new Class[] {ContainerWrapper.class}); enhancer.setCallback(interceptor); enhancer.setClassLoader(config.getResourceLoader().getClassLoader()); Object proxy = enhancer.create(); wrapper.onLoad(proxy, container); return proxy; }
private Object createServiceInterfaceProxy( String serviceInterfaceClassName, Map seiPortNameToFactoryMap, Map seiClassNameToFactoryMap, ClassLoader classLoader) throws NamingException { boolean initialize = (this.serviceConstructor == null); if (initialize) { Class serviceInterface; try { serviceInterface = classLoader.loadClass(serviceInterfaceClassName); } catch (ClassNotFoundException e) { throw (NamingException) new NamingException( "Could not load service interface class " + serviceInterfaceClassName) .initCause(e); } // create method interceptors Callback callback = new ServiceMethodInterceptor(seiPortNameToFactoryMap); this.methodInterceptors = new Callback[] {NoOp.INSTANCE, callback}; // create service class Enhancer enhancer = new Enhancer(); enhancer.setClassLoader(classLoader); enhancer.setSuperclass(ServiceImpl.class); enhancer.setInterfaces(new Class[] {serviceInterface}); enhancer.setCallbackFilter(new NoOverrideCallbackFilter(Service.class)); enhancer.setCallbackTypes(new Class[] {NoOp.class, MethodInterceptor.class}); enhancer.setUseFactory(false); enhancer.setUseCache(false); this.enhancedServiceClass = enhancer.createClass(); // get constructor this.serviceConstructor = FastClass.create(this.enhancedServiceClass).getConstructor(SERVICE_CONSTRUCTOR_TYPES); } // associate the method interceptors with the generated service class on the current thread Enhancer.registerCallbacks(this.enhancedServiceClass, this.methodInterceptors); Object[] arguments = new Object[] {seiPortNameToFactoryMap, seiClassNameToFactoryMap}; Object serviceInstance = null; try { serviceInstance = this.serviceConstructor.newInstance(arguments); } catch (InvocationTargetException e) { throw (NamingException) new NamingException("Could not construct service instance") .initCause(e.getTargetException()); } if (initialize) { for (Iterator iterator = seiPortNameToFactoryMap.values().iterator(); iterator.hasNext(); ) { SeiFactoryImpl seiFactory = (SeiFactoryImpl) iterator.next(); try { seiFactory.initialize(serviceInstance, classLoader); } catch (ClassNotFoundException e) { throw (NamingException) new NamingException("Could not load service interface class; " + e.getMessage()) .initCause(e); } } } return serviceInstance; }
private boolean tryInjectManager() { Class<?> serverClass = serverHandler.getClass(); Enhancer ex = new Enhancer(); Callback sendPacketCallback = new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { Object packet = args[0]; if (packet != null) { packet = handlePacketSending(packet); // A NULL packet indicate cancelling if (packet != null) args[0] = packet; else return null; } // Call the method directly return proxy.invokeSuper(obj, args); }; }; Callback noOpCallback = NoOp.INSTANCE; // Share callback filter - that way, we avoid generating a new class for // every logged in player. if (callbackFilter == null) { callbackFilter = new CallbackFilter() { @Override public int accept(Method method) { if (method.equals(sendPacketMethod)) return 0; else return 1; } }; } ex.setClassLoader(classLoader); ex.setSuperclass(serverClass); ex.setCallbacks(new Callback[] {sendPacketCallback, noOpCallback}); ex.setCallbackFilter(callbackFilter); // Find the Minecraft NetServerHandler superclass Class<?> minecraftSuperClass = getFirstMinecraftSuperClass(serverHandler.getClass()); ExistingGenerator generator = ExistingGenerator.fromObjectFields(serverHandler, minecraftSuperClass); DefaultInstances serverInstances = null; // Maybe the proxy instance can help? Object proxyInstance = getProxyServerHandler(); // Use the existing server proxy when we create one if (proxyInstance != null && proxyInstance != serverHandler) { serverInstances = DefaultInstances.fromArray( generator, ExistingGenerator.fromObjectArray(new Object[] {proxyInstance})); } else { serverInstances = DefaultInstances.fromArray(generator); } serverInstances.setNonNull(true); serverInstances.setMaximumRecursion(1); Object proxyObject = serverInstances.forEnhancer(ex).getDefault(serverClass); // Inject it now if (proxyObject != null) { // This will be done by InjectedServerConnection instead // copyTo(serverHandler, proxyObject); serverInjection.replaceServerHandler(serverHandler, proxyObject); serverHandlerRef.setValue(proxyObject); return true; } else { return false; } }
@SuppressWarnings("unchecked") public <T> T createProxy( Class<T> toMock, InvocationHandler handler, Method[] mockedMethods, ConstructorArgs args) { Enhancer enhancer = createEnhancer(toMock); MockMethodInterceptor interceptor = new MockMethodInterceptor(handler); if (mockedMethods != null) { interceptor.setMockedMethods(mockedMethods); } enhancer.setCallbackType(interceptor.getClass()); Class<?> mockClass; try { mockClass = enhancer.createClass(); } catch (CodeGenerationException e) { // ///CLOVER:OFF (don't know how to test it automatically) // Probably caused by a NoClassDefFoundError, to use two class loaders at the same time // instead of the default one (which is the class to mock one) // This is required by Eclipse Plug-ins, the mock class loader doesn't see // cglib most of the time. Using EasyMock and the mock class loader at the same time solves // this LinkedClassLoader linkedClassLoader = new LinkedClassLoader(toMock.getClassLoader(), ClassProxyFactory.class.getClassLoader()); enhancer.setClassLoader(linkedClassLoader); mockClass = enhancer.createClass(); // ///CLOVER:ON } try { Enhancer.registerCallbacks(mockClass, new Callback[] {interceptor}); if (args != null) { // Really instantiate the class Constructor<?> cstr; try { // Get the constructor with the same params cstr = mockClass.getDeclaredConstructor(args.getConstructor().getParameterTypes()); } catch (NoSuchMethodException e) { // Shouldn't happen, constructor is checked when ConstructorArgs is instantiated // ///CLOVER:OFF throw new RuntimeException("Fail to find constructor for param types", e); // ///CLOVER:ON } T mock; try { cstr.setAccessible(true); // So we can call a protected // constructor mock = (T) cstr.newInstance(args.getInitArgs()); } catch (InstantiationException e) { // ///CLOVER:OFF throw new RuntimeException("Failed to instantiate mock calling constructor", e); // ///CLOVER:ON } catch (IllegalAccessException e) { // ///CLOVER:OFF throw new RuntimeException("Failed to instantiate mock calling constructor", e); // ///CLOVER:ON } catch (InvocationTargetException e) { throw new RuntimeException( "Failed to instantiate mock calling constructor: Exception in constructor", e.getTargetException()); } return mock; } else { // Do not call any constructor Factory mock; try { mock = (Factory) ClassInstantiatorFactory.getInstantiator().newInstance(mockClass); } catch (InstantiationException e) { // ///CLOVER:OFF throw new RuntimeException( "Fail to instantiate mock for " + toMock + " on " + ClassInstantiatorFactory.getJVM() + " JVM"); // ///CLOVER:ON } // This call is required. CGlib has some "magic code" making sure a // callback is used by only one instance of a given class. So only // the // instance created right after registering the callback will get // it. // However, this is done in the constructor which I'm bypassing to // allow class instantiation without calling a constructor. // Fortunately, the "magic code" is also called in getCallback which // is // why I'm calling it here mock.getCallback(0); mock.getCallback(0); return (T) mock; } } finally { // To avoid CGLib out of memory issues Enhancer.registerCallbacks(mockClass, null); } }
@Override public ExporterTask getExporter(String type, HibernateToolTask parent, String serviceName) { Enhancer enhancer = new Enhancer(); enhancer.setCallbackType(ExporterTaskInterceptor.class); enhancer.setCallback(new ExporterTaskInterceptor()); ExporterTask proxy = null; if (type.equals("config")) { enhancer.setSuperclass(HibernateConfigExporterTask.class); enhancer.setClassLoader(HibernateConfigExporterTask.class.getClassLoader()); proxy = (HibernateConfigExporterTask) enhancer.create( new Class[] {HibernateToolTask.class, Folder.class}, new Object[] {parent, this.destDir}); } else if (type.equals("java")) { enhancer.setSuperclass(Hbm2JavaExporterTaskWrapper.class); enhancer.setClassLoader(Hbm2JavaExporterTaskWrapper.class.getClassLoader()); proxy = (Hbm2JavaExporterTaskWrapper) enhancer.create( new Class[] {HibernateToolTask.class, Folder.class}, new Object[] {parent, this.destDir}); } else if (type.equals("query")) { enhancer.setSuperclass(QueryExporterTask.class); enhancer.setClassLoader(QueryExporterTask.class.getClassLoader()); proxy = (QueryExporterTask) enhancer.create( new Class[] {HibernateToolTask.class, String.class, Folder.class}, new Object[] {parent, serviceName, this.destDir}); } else if (type.equals("mapping")) { enhancer.setSuperclass(Hbm2HbmXmlExporterTaskWrapper.class); enhancer.setClassLoader(Hbm2HbmXmlExporterTaskWrapper.class.getClassLoader()); proxy = (Hbm2HbmXmlExporterTaskWrapper) enhancer.create( new Class[] {HibernateToolTask.class, Folder.class}, new Object[] {parent, this.destDir}); } else if (type.equals("springConfig")) { enhancer.setSuperclass(HibernateSpringConfigExporterTask.class); enhancer.setClassLoader(HibernateSpringConfigExporterTask.class.getClassLoader()); proxy = (HibernateSpringConfigExporterTask) enhancer.create( new Class[] { HibernateToolTask.class, Folder.class, String.class, String.class, String.class, String.class, boolean.class, boolean.class, String.class, Integer.class }, new Object[] { parent, this.destDir, serviceName, this.packageName, this.dataPackage, this.className, this.useIndividualCRUDOperations, this.impersonateUser, this.activeDirectoryDomain, this.batchSize }); } return proxy; }