How to Deal With Linkageerrors in Java

How to deal with LinkageErrors in Java?

LinkageError is what you'll get in a classic case where you have a class C loaded by more than one classloader and those classes are being used together in the same code (compared, cast, etc). It doesn't matter if it is the same Class name or even if it's loaded from the identical jar - a Class from one classloader is always treated as a different Class if loaded from another classloader.

The message (which has improved a lot over the years) says:

Exception in thread "AWT-EventQueue-0" java.lang.LinkageError: 
loader constraint violation in interface itable initialization:
when resolving method "org.apache.batik.dom.svg.SVGOMDocument.createAttribute(Ljava/lang/String;)Lorg/w3c/dom/Attr;"
the class loader (instance of org/java/plugin/standard/StandardPluginClassLoader)
of the current class, org/apache/batik/dom/svg/SVGOMDocument,
and the class loader (instance of ) for interface org/w3c/dom/Document
have different Class objects for the type org/w3c/dom/Attr used in the signature

So, here the problem is in resolving the SVGOMDocument.createAttribute() method, which uses org.w3c.dom.Attr (part of the standard DOM library). But, the version of Attr loaded with Batik was loaded from a different classloader than the instance of Attr you're passing to the method.

You'll see that Batik's version seems to be loaded from the Java plugin. And yours is being loaded from " ", which is most likely one of the built-in JVM loaders (boot classpath, ESOM, or classpath).

The three prominent classloader models are:

  • delegation (the default in the JDK - ask parent, then me)
  • post-delegation (common in plugins, servlets, and places where you want isolation - ask me, then parent)
  • sibling (common in dependency models like OSGi, Eclipse, etc)

I don't know what delegation strategy the JPF classloader uses, but the key is that you want one version of the dom library to be loaded and everyone to source that class from the same location. That may mean removing it from the classpath and loading as a plugin, or preventing Batik from loading it, or something else.

java.lang.LinkageError Error in Class Loading

I think this happened for me when I included a library twice.

How do I correct a Java LinkageError exception?

I am suspecting you have a jar that is being loaded in two different classloaders. By that I mean, your websphere server on startup loads that jar or has an endorsed directory with that jar. Also your EAR you are deploying has that jar in its lib. The two can conflict at runtime

What I would suggest is to find out which jar ManageRecordsConsumerServlet belongs to and either remove it from your EAR lib or your Websphere endorsed lib (best would be your EAR lib).

ServiceConfigurationError caused by LinkageError in WebSphere

The issue here is a cross-linkage between the application and server's copies of the JAXB API, JAX-WS API, and JAX-WS implementation. The application (configured with parent-last class loading delegation, so it searches locally before delegating to parents) contains a JAX-WS implementation and JAXB API/impl, but it does not contain the JAX-WS API. Since JAX-WS references JAXB, we get the following linkage pattern:

1) Some application class references the JAX-WS API. Because it's not packaged in the application, it's loaded from the server libraries.

2) When the API class is linked, it uses its local class loader to find the JAXB API. That, in turn, links it to the server's version as well.

3) JAX-WS uses the thread context class loader to load its implementation. It finds it in the parent-last application.

4) When the implementation class is linked, it uses its local class loader to find the JAXB API, which finds it locally in the application.

5) The implementation now is linked to two versions of the same class:

JAXWSImpl -> JAXWSAPI -> JAXB (server)
JAXWSImpl -> JAXB (app)

The JVM can't tolerate that, and a LinkageError is thrown.

The solution can be approached one of two ways:

1) Add the JAX-WS API to the application - this prevents the initial delegation in #1 above

2) Remove the JAXB API (and implementation, if provided) from the application - this causes the linkage in #4 to delegate down to the server for JAXB, so it's always loaded from the same place.

Either way, the trick is to ensure that all the necessary classes are available to the application through the same class loader.

Java LinkageError while deploying to weblogic

Ok I solved the issue. I found the conflicting dependencies;

Recap:

Using the

weblogic-web-app/container-descriptor

did not work for me:

prefer-web-inf-classes = true

was already set and changing it to prefer application packages only caused more trouble since the project already depended on the prefer classes configuration.

Solution:

I used findjar for looking up in which jar's my QName resides and put these jar's in my memory.

Then by using

mvn dependency:tree

I got all the dependencies and sub dependencies of my project (wont post it because the POM is BIG).

I noticed that there were two dependencies with 'stax' in their name. One 'official' stax jar (sub dependency of xmlbeans) and one from genronimo (sub dependency of axiom). So I did some research and found out that the geronimo stax is an implementation/adaption on the original stax jar and therefore both contain QName.
I removed the original stax from my dependency list:

    <dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.5.0</version>
<!-- Excluding XMLBean's STAX because we want to use axiom/geronimo-stax -->
<exclusions>
<exclusion>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
</exclusion>
</exclusions>
</dependency>

Hope it helps :)



Related Topics



Leave a reply



Submit