Class Loaders
A separate class loader is used to load the classes of each plugin. This allows each plugin to use a different library version, even if the same library is used by the IDE itself or by another plugin.
Third-Party Software and Licenses lists all bundled libraries and their versions for each product.
Gradle 7 introduced implementation
scope, replacing compile
scope. For this setup, to use project defined dependency instead of the bundled IDE version, add the following snippet to your Gradle build script:
configurations.all {
resolutionStrategy.sortArtifacts(ResolutionStrategy.SortOrder.DEPENDENCY_FIRST)
}
configurations.all {
resolutionStrategy.sortArtifacts(ResolutionStrategy.SortOrder.DEPENDENCY_FIRST)
}
By default, the main IDE class loader loads classes that are not found in the plugin class loader. However, in the plugin.xml file, you may use the <depends>
element to specify that a plugin depends on one or more other plugins. In this case, the class loaders of those plugins will be used for classes not found in the current plugin. This allows a plugin to reference classes from other plugins.
Some libraries use ServiceLoader
to detect and load implementations. For this to work in a plugin, the context class loader must be set to the plugin's classloader and restored afterwards with the original one around initialization code:
Thread currentThread = Thread.currentThread();
ClassLoader originalClassLoader = currentThread.getContextClassLoader();
ClassLoader pluginClassLoader = this.getClass().getClassLoader();
try {
currentThread.setContextClassLoader(pluginClassLoader);
// code working with ServiceLoader here
} finally {
currentThread.setContextClassLoader(originalClassLoader);
}
Thanks for your feedback!