OSGi LinkageError with two library plugins providing the same packages and classes, but different versions

356 views Asked by At

I have two library plugins, each of the same library that have the same API, but different versions

One of the library plugins has the following in the MANIFEST.MF:

Export-Package: com.package1.packagename1;version=1.0.0,
com.package2.packagename2;version=1.0.0

The second library plugin has the following defined in the MANIFEST.MF:

Export-Package: com.package1.packagename1;version=1.1.0,
com.package2.packagename2;version=1.1.0

The plugin that uses this API has the following defined in the MANIFEST.MF:

Import-Package: com.package1.packagename1;version="[1.0.0,1.1.0]",
com.package2.packagename2;version="[1.0.0,1.1.0]"

When the plugin that is using Import-Package is activated, it checks a preference value to determine which version of the library the user would like to use. The Activator then uses

bundle.stop() 
bundle.uninstall()

for the library version that is NOT wanted, leaving only the one plugin available to satisfy the Import-Package. Up to this point, everything functions as expected and the correct version of the library can be used without error.

The problem comes in when changing versions. When a user changes the library preference, currently, the application shuts down and asks the user to restart it manually. This guaruntees that the JVM and platform both restart so that I can programmatically stop and uninstall the other version of the plugin. However, when the library consumer plugin attempts to invoke the remaining installed version of the library plugin, the following exception is thrown:

java.lang.LinkageError: loader constraint violation: loader (instance of
org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) previously
initiated loading for a different type with name "com/package1/packagename1/ClassName"

There was a similar problem here, but the solution seemed to be rename some of the packages to just avoid the issue. This solution will not work for me as the entire point is them having the exact same API and just changing out the underlying library version.

Restarting the JVM and Platform again without changing the preference fixes this issue, but I'd much rather find a solution that doesn't require users to restart the application two times to change a library version. Is there another way to solve this problem to avoid this linkage error?

1

There are 1 answers

2
Christian Schneider On

It sounds like the classloader using the other library is still active.

You have to make sure the bundle using the library is not holding any references to objects and classes when it is stopped. Only then can the bundle classloader be cleaned up.

Additionally you have to refresh all bundles using the library. This will rewire them to the new library.