Over a million developers have joined DZone.

JarJar: solves class loading conflicts

· Java Zone

Bitbucket is for the code that takes us to Mars, decodes the human genome, or drives your next car. What will your code do? Get started with Bitbucket today, it's free.

Sometimes you're faced with a conflict between two versions of the same JAR in your classpath that cannot be resolved. Here's an example:

Weblogic uses Antlr (the Java compiler-compiler) for parsing EJB-QL queries. Hibernate 3 uses Antlr to parse HQL queries. The Weblogic kernel only sees its own Antlr version through its ClassLoader. Hibernate however sees Weblogic's version and its own. It cannot use Weblogic's version, however this is the one that will get loaded (it has priority in the ClassLoader hierarchy). More details on this issue can be found here.

Weblogic has an option to change the class loading priorities but this may cause other class loading issues like LinkageError. So is there no solution?

Enter JarJar, a lovely little Ant task that not only makes one jar out of many, it can also change package names of certain classes in byte-code! This effectively solved the titanic Weblogic/Hibernate clash we were facing.

Here's the Ant script we used to create a modified Hibernate JAR that also contains renamed Antlr classes:

<project name="jarjar-to-the-rescue">
    <property name="jarfile" value="hibernate-3.2.5.ga-jarjar.jar"/>
    <path id="classpath">
        <pathelement location="jarjar-1.0rc6.jar"/>
        <pathelement location="asm-2.2.3.jar"/>
    <taskdef name="jarjar" 
            classname="com.tonicsystems.jarjar.JarJarTask" classpathref="classpath"/>
    <delete file="${jarfile}"/>
    <jarjar destfile="${jarfile}">
        <zipfileset src="hibernate-3.2.5.ga.jar"/>
        <zipfileset src="antlr-2.7.6.jar"/>
        <rule pattern="antlr.**" result="org.hibernate.jarjar.antlr.@1"/>

This script will create a new JAR file (hibernate-3.2.5.ga-jarjar.jar) that contains the contents of both Hibernate and Antlr jars. I will change the package name of all Antlr classes from antlr.* to org.hibernate.jarjar.antlr.*. It will also change this package in all Hibernate classes that depend on Antlr classes.

With this modified Hibernate JAR file there are still two Antlr versions on the class path. Since Hibernate no longer loads the antlr.* classes the conflict is effectively resolved. Example project and modified Hibernate JAR file attached.

Happy coding!

Bitbucket is the Git solution for professional teams who code with a purpose, not just as a hobby. Get started today, it's free.


Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}