It looks like this code is trying to execute a protected ClassLoader method by making it accessible.
I've added a doPriviledged() call around the code that invokes CtClass.toClass().
That still wasn't working; so we've been trying different combinations of grants in the security policy.
Any idea what is happening here? Also, shouldn't there be a way to pass the correct ProtectionDomain into Javassist?
Also, it would be really handy if Javassist would wrap the exception; we might find the underlying cause of the IllegalAccessException if it would. We can't quite attach the debugger because of the environment.
A security policy/ProtectionDomain cannot be used to bypass Java language access checking. The security policy only affects java.security.Policy.implies type of checks. If it was a security policy issue the failure should have been on the "method.setAccessible(true)" call, and this should produce a SecurityException, not IllegalAccessException.
The CannotCompileException is wrapping the exception passed to its ctor, but apparently not overriding the correct print method to expose the cause. It should be using the jdk1.4.2 version of the ctors to pass the cause to its superclass.
I would distill the example down to a simple standalone java client that exercises the indicated call stack to identify what is really failing.
The problem doesn't manifest itself standalone, in JBoss 4 or in Tomcat 5, or (as best I can tell) anywhere but inside Websphere.
I'm waiting for my clients to report back on what they found using the debugger and a break point.
Another idea is to use JDK1.4's initCause().
Scott, can Javassist stop supporting JDK1.3?
We are not bundling aop/ejb3 in 3.2.x which is our only platform with a jdk1.3 requirement, so yes, javassist should be able to move up to 1.4.2 as a minimum platform.
I'd prefer Javassist 3.0 to keep JDK 1.3 compatibility, since I use it in HiveMind and Tapestry, which both have a requirement (for the meantime) to stay compatible with JDK 1.3.
Perhaps you could use reflection to set invoke initCause() only if available? That's a common trick for dealing with JDK 1.3 vs 1.4.
I am hitting a similar problem when trying to instrument code from JBoss AOP. I am attaching my stack trace and would like to learn about fixes if any are available.
[error] failed to transform: org.eclipse.osgi.framework.internal.core.BundleContextImpl.. Do verbose mode if you want full stack trace.
seems to be a bug in the ibm jdk 1.4.1.
I debugged the code and the problem seems to be, that java.lang.reflect.Method-objects are reused in some way.
The first call to toClass is ok - a Method-object is created and stored.
As you can see in the code-snippet posted above, on leaving toClass, the stored Method-object has the state override=false.
On subsequent calls to toClass, the stored Method-object is used by the methodAccessor of new Method-objects to determine the access-permission.
So invoke fails with an IllegalAccessException, because the override-state of the new object is ignored.