Wednesday, January 12, 2011

JacORB in Jetty

There is a nasty JVM bug with class verification when you use JacORB in a webapp in Jetty. The issue only occurs when you use a custom classloader (as Jetty does) and load the CORBA in JacORB which replace the default implementation in the JDK. The characteristic message is:

java.lang.VerifyError: (class: org/jacorb/orb/Delegate, method: getReference signature: (Lorg/jacorb/poa/POA;)Lorg/omg/CORBA/portable/ObjectImpl;) Incompatible object argument for function call

The problem has been ongoing since at least 2004 that I can tell from googling without much progress. It happens to other containers than Jetty.

The solution is to ensure the JacORB classes are loaded with the system classloader, not the custom classloader in the webapp container. The only way this can happen is

  1. The jacorb jar and its dependencies are not in WEB-INF/lib so Jetty cannot find them there with its classloader, forcing delegation to the system classloader.
  2. The system classloader has the jacorb jar and its dependencies prepended to the boot classpath so they can take precedence over the default CORBA implementation in the JDK.

As I use maven, this means my POM for building the war includes:

<dependency>
    <groupId>jacorb</groupId>
    <artifactId>jacorb</artifactId>
    <optional>true</optional>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <optional>true</optional>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <optional>true</optional>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>${ch.qos.logback.version}</version>
    <optional>true</optional>
    <scope>provided</scope>
</dependency>

(I am relying on a parent pom to define versions for these)

And my command line to run Jetty from maven with the excellent jetty-maven-plugin (I am on Windows for this project):

$ MAVEN_OPTS='-Xbootclasspath/p:jacorb-2.3.1jboss.patch01-brew.jar\;slf4j-api-1.6.1.jar\;logback-classic-0.9.26.jar\;logback-core-0.9.26.jar -Dorg.omg.CORBA.ORBClass=org.jacorb.orb.ORB -Dorg.omg.CORBA.ORBSingletonClass=org.jacorb.orb.ORBSingleton' mvn jetty:run-war

I am glad this is finally behind me; a day and a half I could have better spent playing elsewhere.

No comments: