I'm trying to create a proxy with cglib for a class that only has a private constructor. I can't change the visibility, as it's a library method.
I found this post, and followed the instrcutions to override the filterConstructors method, but when cglib tries to call it I get an java.lang.IllegalAccessError.
Can I bypass this limitation somehow?
Cglib works by subclassing. The cglib class can therefore never access the constructor of the proxied class.
What you can tryto do is to redefine the existing class. For this, you can use a library such as Byte Buddy.
Related
I would like to use a CGLIB proxy to add my own reusable equals() method to existing objects.
The objects do not necessarily implement any interfaces and I need to be able to cast the proxied object to the original class (without getting the target of the proxy).
Unfortunately, it seems that CGLIB implements its own equals() method and makes sure that only that method is called: there is a private static class (EqualsInterceptor) whose method intercept() implements a reasonable logic to compare proxied objects.
The problem is that this method, at the end, delegates the comparison to the target objects: I need instead to reuse some logic that is not implemented by the target classes.
Using a standard proxy, I was able to intercept the call to the equals() method and execute my logic. The problem is that these kind of proxies cannot be cast to the original class.
It seems that the only way is to rewrite some classes in the CGLIB library. It does not seem a good idea.
No, this is not possible using cglib.
You can use another library such as Byte Buddy which allows you to intercept equals/hashCode just like any other method.
For disclosure: I am the author of Byte Buddy and a maintainer for cglib which are both Apache 2.0 licensed.
I am working on dynamic proxy creation on concrete classes. Since java's plain Proxy class does help only with Interfaces , I chose CGLIb.
I am using Enhancer class with MethodInterceptor for intercepting the methods of my proxy and I am able to intercept all method calls but static methods.
Is there any way to intercept calls to static methods using CGLIb?
This is not possible, cglib instruments classes by creating a subclass where all methods are overriden to apply the interception logic. This is not possible for static methods such that cglib does not support this.
I'm using CGLib to proxy classes. I've hit a problem where I can not enhance anonymous classes because they don't have a default constructor.
My code looks like this:
Enhancer enhancer = new Enhancer();
enhancer.setCallback(new MethodInterceptor() { .... });
enhancer.setSuperclass(type); // type is the Class I'm trying to enhance
enhancer.create();
However this throws the following exception if the enhanced class is anonymous (no default constructor).
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
Is there a way to go around this?
A JVM's verifier assures that you call a valid constructor chain. The only way around this is to disable the verifier by command line when starting up the JVM and this is nothing you generally want to do as it introduces several insecurities to your application.
Thus, you will have to call a valid constructor of your anonymous class which is imitated by the subclass that is created by cglib. This class's constructor thus takes an instance of its enclosing class as its argument. If you use cglib to create a pure proxy that never calls a real method, you can consider handing null to this constructor but you still need to select the right constructor before handing the argument.
You can achieve this by calling:
enhancer.create(new Class<?>[] {type.getEnclosingClass()}, new Object[] {null})
where the above call selects the correct constructor and initializes the anonymous class's outer instance field with a null value.
Alternatively, you could use the internal OpenJDK class ReflectionFactory in order to create an instance without calling any constructor. This is possible after calling enhancer.createClass(). This requires however additional preparation as you need to specify a different callback.
However, you might just want to drop cglib alltogether. As a disclaimer, I am the author of an alternative library I want to recommend to you. Using Byte Buddy, you have more freedom in creating classes and it is easier to define your logic using it. Using Byte Buddy, you can write
new ByteBuddy()
.subclass(type)
.method(any()).intercept(MethodDelegation.to(new Object() {
#RuntimeType
public Object intercept(#SuperCall Callable<?> c,
#Origin Method m,
#AllArguments Object[] a) throws Exception {
// implement your interception logic
}
}).make();
and achieve the same logic. Simply remove the (annotated) arguments you do not need for calling your interception.
I have provider which should inject javax.mail.Session (provider looks it up in env. context of tomcat) as singleton. There is a problem when I use field injection somewhere in code:
java.lang.IllegalArgumentException: Cannot subclass final class class javax.mail.Session
Is there a way to go round this? Only clues that I've found point to Spring AOP/Proxies.
Thanks && regards
Look at this http://code.google.com/p/google-guice/wiki/AOP. It seems that there is some limitations:
Limitations
Behind the scenes, method interception is implemented by generating
bytecode at runtime. Guice dynamically creates a subclass that applies
interceptors by overriding methods. If you are on a platform that
doesn't support bytecode generation (such as Android), you should use
Guice without AOP support.
This approach imposes limits on what classes and methods can be
intercepted:
Classes must be public or package-private. Classes must be non-final
Methods must be public, package-private or protected Methods must be
non-final Instances must be created by Guice by an #Inject-annotated
or no-argument constructor
I'm creating proxies with javassist ProxyFactory. When creating a single proxy all works fine.
However, when I pass a proxied object to the proxying mechanism, it fails with
javassist.bytecode.DuplicateMemberException: duplicate method: setHandler in com.mypackage.Bean_$$_javassist_0_$$_javassist_1
I'm creating the proxies with this:
public Object createProxiedInstance(Object originalInstance) throws Exception {
Class<?> originalClass = instance.getClass();
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(originalClass);
factory.setHandler(new MethodHandler() {..});
Class<T> proxyClass = factory.createClass();
return proxyClass.newInstance();
}
So, how do I create proxies of proxies?
Update: The actual problems is that each proxy implements the ProxyObject which defines setHandler(..) method. So the 2nd proxy is trying to redefine the method, instead of overriding it in the subclass.
The problem was (actually, it's the same with CGLIB - I tried it using commons-proxy) that I should not try to create a proxy class of the proxy class. The second proxy should again be of the original class. So adding the following line resolves the problem:
if (instance instanceof ProxyObject) {
originalClass = originalClass.getSuperclass();
}
And an advice - if you can use some sort of interceptors (like the ones defined in commons-proxy), do it instead of using multiple proxies.
Its a rather late answer but you might still be interested in knowing this:
Javassist proxies are implemented rather naively. In your above code, Javassist will always create a proxy class with the following methods:
A method for any overridable method of the base class
Two methods to (a) get a proxy handler (getHandler) and (b) set a proxy handler (setHandler)
The names of the two latter methods are hardcoded by Javassist and represented by the ProxyObject interface. If you now create a proxy class of a proxy class, Javassist would schedule the creation of ProxyObject's methods twice. Once by the first condition and once by the second condition.
You could avoid this by setting a MethodFilter which specifies to not override the ProxyObject's methods such that javassist would only create the methods by the second condition. However, this would imply that you could not longer set a ProxyObject for the super class proxy without directly accessing the corresponding field via reflection. Therefore, your approach is probably the cleanest.
cglib defines callbacks per class and not per instance such that this problem with cglib is slightly different but results in another conflict.
However, if you want to create proxy classes that do not suffer these shortcomings, you might be interested in my library Byte Buddy which I wrote after getting frustrated working with cglib and javassist when working in corner cases. If you are working with runtime code generation I hope that it might help offer you some flexibility that the other libraries lack.