JBoss 7.1 and java.lang.IllegalAccessError invoking private methods

At my company we’re starting to use JBoss 7.1 and came across a problem with its new classloading behavior. We’re deploying an EAR with the following structure:

  • EAR
    • lib
      • common.jar
    • ejb.jar

In common.jar are classes included, that have a package-private constructor that should only be used within ejb.jar’s factory. For this the factory and the specific classes are located in the same package, but in different jar’s. So a client can only use the public constructor of the classes whereas the ejb.jar can invoke the internal contructor not visible to the client.

With JBoss 5.1.0 this worked without a problem. But when we tried the same with JBoss 7.1, we encountered the following Error:

Caused by: java.lang.IllegalAccessError: tried to access method CommonClass.<init>()V from class FactoryClass

This is due to the fact that with JBoss 7 each jar is loaded by a separate classloader. We tried the suggested workaround using the jboss-deployment-structure.xml mentioned in a similar JIRA ticket, but always ended up in two separate classloaders for the jar’s.

Since it is a limitation of the underyling JVM and not JBoss 7 we simply added the factory to the common.jar and created a common-client.jar via maven assembly where the factory is excluded. Not nice, but helped us to go on.

  • sur

    Can you please explain more on ‘ added the factory to the common.jar and created a common-client.jar via maven assembly’ and how you did that.

    • nightprogrammer

      Initially, the factory was within the mentioned ejb.jar that resided on the server only. The class, the factory was dealing with, was within the common.jar. That constellation led to the problem described.

      To fix that, we moved the factory to the common.jar too so that both classes were within the same jar. So ejb.jar used that common.jar on the server side.

      To avoid that a client uses the factory from the common.jar, we simply created another common-client.jar via maven assembly, that simply excluded the factory from common.jar.

      This way, on server side everything was in the common.jar, on the client side there was a special common-client.jar that missed the factory.

      For more details about maven assemblies, please take a look at the maven hompage.