The logs contain an exception: java.lang.LinkageError: Class my/package/MyClass violates loader constraints
.
While linkage errors have a number of causes, a common cause for OSGi plugins is when two copies of the same class try to interact through a shared class. Most commonly, this is because the plugin is bundling a dependent JAR in META-INF/lib
, but that same JAR is also available via the host application in its WEB-INF/lib
. If the plugin interacts with an object that references the dependency, the plugin's classloader may recognise that the dependency class instance is a different one than the one it knows about and will therefore throw the LinkageError.
For example, let's assume the following scenario:
commons-fileupload
, but does not export or import any of its packagescommons-fileupload
.commons-fileupload
, and the filter is set to be run before dispatch.commons-fileupload
.When plugin A's filter is executed, its classloader will notice that the request has been wrapped with classes with the same name as its commons-fileupload
but with different instances. Plugin A's classloader will then throw a LinkageError.
The quick solution is to not bundle any third-party JARs in your plugin. However, if you need to do so, ensure that the packages are exported and imported via your OSGi manifest to ensure your plugin will bind to the packages provided by the host application, if available. This technique is not foolproof, since your exported packages could be slightly newer than the ones provided by the host application, and therefore OSGi will bind you to your own packages instead of the host application's packages. If you are sure that the host application or another plugin does not already provide your dependency, or that there is no chance of your plugin interacting with objects that reference a different version of your dependency, then you can privately bundle dependencies.
This troubleshooting tip applies to OSGi (version 2) plugins and possibly dynamic legacy Confluence plugins.
Rate this page: