How to work with LinkageErrors in Java?

Developing an XML-based Java application, I recently encountered an interesting problem in Ubuntu Linux.

My application using the Java Plugin Framework seems unable to convert dom4j , the generated XML document, into the Batik implementation of the SVG specification.

On the console, I find out that an error has occurred:

 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 / SVGOM Document, and the class loader (instance of <bootloader>) for interface org / w3c / dom / Document have different Class objects for the type org / w3c / dom / Attr used in the signature
     at org.apache.batik.dom.svg.SVGDOMImplementation.createDocument (SVGDOMImplementation.java:149)
     at org.dom4j.io.DOMWriter.createDomDocument (DOMWriter.javahaps61)
     at org.dom4j.io.DOMWriter.write (DOMWriter.java:138)

I believe the problem is caused by a conflict between the source classloader from the JVM and the classloader deployed within the plugin.

As far as I know, it is not possible to determine the class loader for the structure used. It may be possible to hack, but I would prefer a less aggressive approach to solving this problem, because (for some reason) this only happens on Linux systems.

Have any of you encountered such a problem and have any idea how to fix it or at least solve this problem?

+48
java linux classloader linkageerror
Oct 28 '08 at 19:18
source share
5 answers

LinkageError is what you get in the classic case when you have a C class loaded with more than one class loader, and these classes are used together in the same code (comparison, casting, etc.). It does not matter if it is the same class name or even if it is loaded from an identical jar - a class from one class loader is always treated as another class if it is loaded from another class loader.

The post (which has been improving for many 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 resolving the SVGOMDocument.createAttribute () method, which uses org.w3c.dom.Attr (part of the standard DOM library). But the version of Attr downloaded by Batik was loaded from a different classloader than the Attr instance that you pass to the method.

You will see that the Batik version seems to be loading from the Java plugin. And your boot from "", which is most likely one of the built-in JVM loaders (boot classpath, ESOM or classpath).

Three outstanding bootloader classes:

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

I don’t know what kind of delegation strategy the JPF class loader uses, but the key is that you want one version of the dom library to be loaded, and all to point this class from the same place. This could mean removing it from the class path and loading it as a plugin or preventing Batik from loading or something else.

+53
Oct 28 '08 at 10:00
source share

Sounds like a class loader hierarchy issue. I cannot determine in which environment your application is deployed, but sometimes this problem can occur in a web environment - where the application server creates a hierarchy of class loaders that resembles something like:

javahome / lib - as root
appserver / lib - as a child of root

webapp / WEB-INF / lib - as a child of a root child, etc.

Typically, class loaders delegate the loading to their parent class loader (this is called " parent-first "), and if this class loader cannot find the class, then it tries to execute the class loader. For example, if a class deployed as a JAR in webapp / WEB-INF / lib tries to load a class, it first requests a class loader corresponding to loading the appserver / lib class (which, in turn, requests the class loader corresponding to javahome / lib to load class), and if this search failed, then WEB-INF / lib searches for a match to this class.

In a web environment, you may run into problems with this hierarchy. For example, one error / problem that I encountered earlier was that the class in WEB-INF / lib depended on the class deployed to appserver / lib, which in turn depended on the class deployed to WEB-INF / lib. This caused a malfunction because, since class loaders can delegate to the parent class loader, they cannot delegate the tree back. Thus, the WEB-INF / lib class loader would specify the appserver / lib class loader class, the appserver / lib class loader would load this class and try to load the dependent class and fail because it could not find this class in appserver / lib or javahome / Lib.

So, although you cannot deploy your application in a web server or application environment, my explanation too long may be applicable to you if your environment has a hierarchy of loader classes. Does it have? Is JPF a bit of a class loader magic to be able to implement its plugin functions?

+13
Oct 28 '08 at 20:22
source share

Maybe this will help someone because it is very good for me. The problem can be solved by integrating your own dependencies. Follow these simple steps.

First check the error, which should be like this:

  • Method execution error:
  • java.lang.LinkageError: violation of bootloader restriction:
  • when resolving the method "org.slf4j.impl. StaticLoggerBinder .getLoggerFactory () Lorg / slf4j / ILoggerFactory;"
  • class loader (instance org / openmrs / module / ModuleClassLoader) of the current class, org / slf4j / LoggerFactory ,
  • and the class loader (instance org / apache / catalina / loader / WebappClassLoader) for the allowed class, org / slf4j / impl / StaticLoggerBinder ,
  • have different class objects for the type taticLoggerBinder.getLoggerFactory () Lorg / slf4j / ILoggerFactory; used in signature



  1. Look at the two highlighted classes. Google searches for them, for example, “Downloading the StaticLoggerBinder.class file” and “Downloading the LoggeraFactory.class file”. This will show you the first or in some cases the second link (website http://www.java2s.com ), which is one of the jar versions that you included in your project. You can easily identify it yourself, but we depend on google;)

  2. After that, you will find out the jar file name, in my case it looks like slf4j-log4j12-1.5.6.jar and slf4j-api-1.5.8

  3. Now the latest version of this file is available here http://mvnrepository.com/ (virtually the entire version is up to date, this is the site where maven can get your dependencies from).
  4. Now add both files depending on the latest version (either keep both versions of the file the same or the selected version is outdated). Below is the dependency you should include in pom.xml


 <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.7</version> </dependency> 



How to get dependecy definition from Maven Site

+6
Jun 24. '14 at 20:03
source share

Can I specify a class loader? If not, try specifying the context class loader as follows:

 Thread thread = Thread.currentThread(); ClassLoader contextClassLoader = thread.getContextClassLoader(); try { thread.setContextClassLoader(yourClassLoader); callDom4j(); } finally { thread.setContextClassLoader(contextClassLoader); } 

I am not familiar with the Java Plugin Framework, but I write code for Eclipse, and from time to time I encounter similar problems. I cannot guarantee that this will fix, but it is probably worth doing.

+5
Oct 28 '08 at 20:28
source share

Answers from Alex and Matt are very helpful. I could take advantage of their analysis.

I had the same problem when using the Batik library in the RCP NetBeans infrastructure, and in the Batik library as a "library library module". If any other module uses XML-apis, and no dependency on Batik is required and is not installed for this module, the problem of violating the restrictions of the loader class occurs with similar error messages.

In Netbeans, individual modules use specialized class loaders, and dependencies between modules imply appropriate class delegation routing.

I could solve the problem by simply omitting the jml-apis jar file from the Batik library package.

+3
Nov 23 '09 at 16:56
source share



All Articles