How to solve a “java.lang.LinkageError: ” between two JAR files?

A java.lang.LinkageError happens when “a class has some dependency on another class; however, the latter class has incompatibly changed after the compilation of the former class.” [Java Platform SE 6 API Docs on LinkageError]. Normally, the error is more concretely defined by subclasses of LinkageError, but not always. There are multiple reasons possible:

  1. You have a JAR file in your project that requires another JAR file that’s not in your project. In this case, the latter JAR file is installed somewhere on your system. It is found, but it’s version differs from the version where the JAR file in your project was compiled against. So to speak, the JAR file “changed (in version) after the compilation of the JAR file that’s in your project”.
    A solution (sometimes possible) is to include the requiring JAR as source code into your project. Then, it is comiled itself, and correctly linked against the available version of the required JAR file.
    The alternative, obvious solution is to let the JAR find its expected version of the required JAR files. You may influence this by the order of entries in the Java build path, or if you do Eclipse plugin development and you want JAR files within your plugin to be found, in the plugin classpath in MANIFEST.MF.
  2. You run into an error of Eclipse 3.3.1.1. You recognize this if the java.lang.linkage error persists even if both the requiring and the required JAR files are replaced by source versions in the Eclipse project. (This bug possibly applies only to Eclipse plugin projects.) If this is the case, the required library is one that’s also part of the Java system library. It seems that the Eclipse framework uses its own class loader and replaces the Java class loader, or something with similar effect. The effect is that at runtime, the code refers to other code (always the library that’s part of the Java system library) than at compile time (the library within the same or another plugin project). So again, the required JAR file “changed” (in version) from compile time to runtime.
    Solution: include the requiring JAR as source code, and remove all duplicates of the library from your projects, so that the only installed version of the required JAR library is in the Java system library. Now both at compile and runtime, this is the only thing where requiring code can refer to.

A concrete example for the Eclipse bug described above: the error message was “java.lang.LinkageError: org/xml/sax/ContentHandler” in a plugin used to capsule JDOM code (as source, not as a JAR file).

Due to the bug, at runtime JDOM code always used the Java system library’s SAX when doing “import org.xml.sax.ContentHandler”. Regardless of what the code referred to at compile time: SAX in a JAR file in the same or a required plugin project, SAX as source code in the same source folder of the same plugin project etc..

Also, using the “order” feature when configuring the Java build path of the JDOM plugin project did not help: “plugin dependencies” can be placed above “Java system library”, but regardless of that setting, at runtime the Java system library was used. And this was a JAR file with a different version than what the project was compiled against at compile time … .

The solution was this: remove the dependency from another plugin that contained SAX as a JAR library, and (!) remove the SAX source and JAR files from the plugin project that encapsuled JDOM. Only one of these steps is not enough. Both together probably made Eclipse compile against the same lib as used at runtime, namely SAX form the Java system library.

To conclude: currently, there seems to be no possibility to use a package in place of a package of the same name that’s supplied by the Java system library; which is an Eclipse bug.


Posted

in

,

by

Tags:

Comments

One response to “How to solve a “java.lang.LinkageError: ” between two JAR files?”

  1. Zbonger

    Thanks a lot for this blog, this has solved my issue.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.