Debugging LinkageErrors in Java

What is a LinkageError in Java?

A jar that is being loaded by two different classloaders can throw a java.lang.LinkageError. For example, your application server (e.g JBoss) on startup loads that jar or has a directory with that jar. Also, your EAR or WAR you are deploying has that jar in its say WEB-INF/lib. The two jars can conflict at runtime. Each class loaded is unique to the class loader even if it has the same package and class name.

What are some of the libraries that cause this pain?

log4j.jar, commons-*.jar, mail.jar, quartz.jar, hibernate*.jar, XML API jars, cglib.jar, antlr.jar, activation.jar, etc

How will you go about debugging and fixing a LinkageError in Java?

#1. Identifying the offending jar and class files with Unix commands

For example, if the “javax.xml.namespace.QName.class” from the deploy and lib folders, you can identify the jars as shown below

Output:

As you can see, “./deploy/MyApp/WEB-INF/stax-api.jar” and “./lib/stax-api.jar” have the “javax.xml.namespace.QName.class”.

This can be further extended using “sed” to print only the offending jar file as shown below. The command shown below:

Output:

#2. Turning on the JVM class loading to verbose with

#3 Check application server’s doco for isolating server level jars from app (e.g. war or ear) level jars

LinkageError can be hard to debug, and you need to understand how the class loader works, and may require application server level tweaking. For example, in JBoss you can exclude server modules as shown below in the “jboss-deployment-structure.xml

The above snippet tells JBoss to exclude the logging modules in JBoss and to load “org.hibernate” modules from its library as opposed to from the war. You need to read the class loading section of your application server’s documentation.

#4 Check or change the classloading strategy on your app server config

By default in the JBoss application server the libraries in the <server instance>/lib take precedence over the jars defined in the application (i.e. ear or war). This ca lead to LinkageErrors as there is a likelihood of same jar files being located in your application as well as in the <server instance>/lib directory. You can resolve this issue by turning off the “java2ParentDelegation“.

You can configure for EAR files via jboss-app.xml

For the WAR files via jboss-web.xml:

You may want learn more about class loading in Java

Java class loading interview Q&A to ascertain your depth of Java knowledge


800+ Java & Big Data Interview Q&As

Top