7 Replies Latest reply: Aug 23, 2005 10:16 AM by Martin Chalupka RSS

IllegalAccessException: java/lang/ClassLoader

Howard Lewis Ship Newbie

One of my clients is using HiveMind (1.1) is having a problem in the following environment:
Websphere 5, IBM JDK 1.4.1 for Windows, Javassist 3.0

javassist.CannotCompileException: by java.lang.IllegalAccessException: java/lang/ClassLoader

at javassist.ClassPool.toClass(ClassPool.java:716)

at javassist.CtClass.toClass(CtClass.java:988)

at org.apache.hivemind.service.impl.HiveMindClassPool.toClass(HiveMindClassPool.java:75)

at org.apache.hivemind.service.impl.CtClassSource.createClass(CtClassSource.java:84)



It looks the failure is in the following code:

public Class toClass(CtClass ct, ClassLoader loader)
throws CannotCompileException
{
try {
byte[] b = ct.toBytecode();
Class cl = Class.forName("java.lang.ClassLoader"); // ****
java.lang.reflect.Method method =
cl.getDeclaredMethod("defineClass",
new Class[] { String.class, byte[].class,
int.class, int.class });
method.setAccessible(true);
Object[] args = new Object[] { ct.getName(), b, new Integer(0),
new Integer(b.length)};
Class clazz = (Class)method.invoke(loader, args);
method.setAccessible(false);
return clazz;
}
catch (RuntimeException e) {
throw e;
}
catch (java.lang.reflect.InvocationTargetException e) {
throw new CannotCompileException(e.getTargetException());
}
catch (Exception e) {
throw new CannotCompileException(e); // Line 716
}
}

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.

  • 1. Re: IllegalAccessException: java/lang/ClassLoader
    Scott Stark Master

    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.

  • 2. Re: IllegalAccessException: java/lang/ClassLoader
    Howard Lewis Ship Newbie

    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.

  • 3. Re: IllegalAccessException: java/lang/ClassLoader
    Shigeru Chiba Expert

    Oh, does CannotCompileException have to
    override printStackTrace(PrintStream)?

    I'll fix it.

    Another idea is to use JDK1.4's initCause().
    Scott, can Javassist stop supporting JDK1.3?

  • 4. Re: IllegalAccessException: java/lang/ClassLoader
    Scott Stark Master

    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.

  • 5. Re: IllegalAccessException: java/lang/ClassLoader
    Howard Lewis Ship Newbie

    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.

  • 6. Re: IllegalAccessException: java/lang/ClassLoader
    Ben Livshits Newbie

    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.
    error getting:org.eclipse.osgi.framework.eventmgr.EventListeners. 'addListener'
    javassist.CannotCompileException: org/jboss/aop/instrument/Untransformable
     at org.jboss.aop.standalone.StandaloneClassPool.toClass(StandaloneClassPool.java:62)
     at javassist.CtClass.toClass(CtClass.java:962)
     at org.jboss.aop.instrument.TransformerCommon.compileOrLoadClass(TransformerCommon.java:119)
     at org.jboss.aop.instrument.CallerTransformer$CallerExprEditor.createOptimizedMethodCalledByMethodInvocationClass(CallerTransformer.java:913)
     at org.jboss.aop.instrument.CallerTransformer$CallerExprEditor.modifyMethod(CallerTransformer.java:309)
     at org.jboss.aop.instrument.CallerTransformer$CallerExprEditor.edit(CallerTransformer.java:233)
     at javassist.expr.ExprEditor.doit(ExprEditor.java:118)
     at javassist.CtBehavior.instrument(CtBehavior.java:362)
     at org.jboss.aop.instrument.CallerTransformer.applyCallerPointcuts(CallerTransformer.java:69)
     at org.jboss.aop.instrument.Instrumentor.applyCallerPointcuts(Instrumentor.java:492)
     at org.jboss.aop.instrument.Instrumentor.transform(Instrumentor.java:572)
     at org.jboss.aop.AspectManager.translate(AspectManager.java:572)
     at org.jboss.aop.AspectManager.transform(AspectManager.java:490)
     at org.jboss.aop.standalone.AOPTransformer.aspectTransform(AOPTransformer.java:59)
     at org.jboss.aop.standalone.AOPTransformer.transform(AOPTransformer.java:51)
     at sun.instrument.TransformerManager.transform(TransformerManager.java:122)
     at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:155)
     at java.lang.ClassLoader.defineClass1(Native Method)
     at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
     at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
     at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
     at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
     at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
     at java.security.AccessController.doPrivileged(Native Method)
     at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
     at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
     at org.eclipse.osgi.framework.internal.core.Framework.initialize(Framework.java:137)
     at org.eclipse.osgi.framework.internal.core.Framework.<init>(Framework.java:95)
     at org.eclipse.osgi.framework.internal.core.OSGi.createFramework(OSGi.java:90)
     at org.eclipse.osgi.framework.internal.core.OSGi.<init>(OSGi.java:31)
     at org.eclipse.core.runtime.adaptor.EclipseStarter.startup(EclipseStarter.java:215)
     at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:127)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
     at java.lang.reflect.Method.invoke(Method.java:585)
     at org.eclipse.core.launcher.Main.basicRun(Main.java:185)
     at org.eclipse.core.launcher.Main.run(Main.java:704)
     at org.eclipse.core.launcher.Main.main(Main.java:688)
    


  • 7. Re: IllegalAccessException: java/lang/ClassLoader
    Martin Chalupka Newbie

    Hi,

    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.

    You have to move to a newer Websphere version, e.g. 5.1.1.5, which comes with jdk 1.4.2

    cheers,
    Martin