J2EE classloading – java.lang.LinkageError
Recently while working on a java enterprise application I came upon a runtime error which later inspired this very post. What will follow will also give you a taste of what proper Maven dependency management should look like. The problem in question was a library call which caused the following to be spit in my error logs:
Caused by: java.lang.LinkageError: loader constraints violated when linking javax/activation/DataHandler class
Translation: This is typically caused to be thrown when two different classloaders load different versions of the same class (different signatures). The underlying cause is essentially including two versions of the same class in your CLASSPATH. Most often the underlying reason is including a JAR file as a dependency in your WAR or EAR which is already included as part of your Servlet Container (my development container happens to be JBoss) or your JVM.
A quick search on findjar.com established that my problem is caused by activation.jar which happens to be included both in my project and the JBoss lib. A quick way to verify this is to extract the EAR or WAR file and have a look for the jar question. In my case I was able to find it in both WEB-INF/lib and JBOSS/lib. A quick fix or a proof of the solution is simply removing one of the instances. For me removing the jar from the EAR proved to be the solution.
Since I like automation when it comes to dependency management I am using Maven to alleviate all the hassles of the manual equivalent. That means that I need to trace which of my build modules includes the jar in question. This is done by building the Maven dependency tree:
mvn dependency:tree
or tunnel the output to a text file which you can examine in your favorite editor (recommended)
mvn dependency:tree > tree.txt
Here it’s worth noting that the dependency feature parameter “outputFile” is not working at the time of writing due to a known bug. After building and searching the tree I can easily identify all the references: javax.xml.bind and javax.xml.ws
Now in order to fix the problem all I need to do is provide the exclusion to both dependencies in my pom.xml:
<exclusions>
<exclusion>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
</exclusion>
</exclusions>
Now my dependency looks like this:
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.0.3</version>
<exclusions>
<exclusion>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
</exclusion>
</exclusions>
</dependency>
Before I run a full build it’s best to verify that there are no more references of activation.jar in my tree by creating the dependency tree again. With that out of the way I am ready to build and deploy my EAR to test the solution. For more on maven dependency mechanism and managing exclusions please refer to the Maven documentation.

Leave a Reply
You must be logged in to post a comment.