How to share libraries between unrelated plugins?

I would like to be able to share libraries between plugins without having to provide these through another plugin which includes the jars in its distribution or have the plugins sharing a library needing to know about each other.

Currently, only classes and interfaces loaded by the IDE can be shared by plugins because they are loaded by a common class loader.

The moment a plugin requires a library which is not part of the IDE, the plugin’s class loader is used to load these classes. Which effectively means the plugins have their own incompatible classes even if they are all using a copy of the same jar.

There are two major use cases where this causes problems:

  1. A plugin tries to access a class instantiated by another plugin, an exception is thrown because the two classes are different. Effectively making it impossible to share singletons or resources across plugins without finding a way to convert the class to an implementation provided by the application class loader, then convert that to a class created by the plugin class loader. Effectively, serializing and de-serializing across plugin container boundaries.

  2. A more serious use case with no work-around is two plugins trying to use the same library which uses a native library in its implementation. In this case the first plugin to use the library succeeds while the second gets an exception that the library is already loaded by another class loader.

Having this issue in my own plugins is a PITA but solvable. The problem occurs if other plugins cause conflicts. This problem existed with JavaFX libraries before they were bundled in the IDE and still exist for non-IDE supplied libraries.

For example, in my Arduino Support plugin, I use jssc library for serial communications which has native libraries for implementation. The same library is used by Serial Monitor plugin and if both are installed one will fail.

A solution I am considering requires only that the plugin authors register such singleton libraries as shared libraries with a third generic plugin. That “Shared Library Registry” plugin provides a component to allow plugins to register shared library(ies) they use. The library(ies) jars are part of each plugin’s distribution but only as a resource and not on the class path. So they will not be loaded by the plugin’s class loader.

The library registry plugin needs to provide ability to inject a class loader for classes in the shared library(ies) into the calling plugin’s container.

If another plugin registers the same shared library it will get the first plugin’s shared class loader, effectively addressing both use cases.

I think this functionality is already present in the IDE implementation because all plugin’s libraries are loaded through its pico-container.

I looked into pico-containers and component adapter documentation. It seems like an ideal implementation would be a cached pico-container with an adapter doing the class loading if the class is not already in the container.

Is it possible to add component adapters to the plugin’s existing pico-container to allow injecting the class loading adapters for shared libraries?

Where is the best place to start looking for implementation details in the open API to figure out how to implement this functionality?

1
1 comment

Fools rush in where angels fear to tread.

After spending the last two evenings with PluginManagerCore, ComponentManagerImpl, and PluginClassLoader, I can only claim getting a better understanding of what is involved and to understand that creating working library sets that can be shared would amount to creating a plugin that shared the libraries and it would be have to be done before plugin class loaders are created and components instantiated.

At least it gave me a change to get a better idea of the inner workings of plugin loading and pico-container use.

0

Please sign in to leave a comment.