[
https://issues.apache.org/jira/browse/KAFKA-8340?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16925879#comment-16925879
]
ASF GitHub Bot commented on KAFKA-8340:
---------------------------------------
gharris1727 commented on pull request #7315: KAFKA-8340: Use PluginClassLoader
while statically initializing plugins
URL: https://github.com/apache/kafka/pull/7315
During plugin class loading and instance creation,
change the current thread's context ClassLoader
to the PluginClassLoader. This prevents issues where
static initialization loads the wrong resources, or
fails to find resources that are inside the plugin.
This change impacts the following classes:
Plugins, DelegatingClassLoader and PluginClassLoader.
In order to verify the original bug and verify the fix,
three test plugins with assertions are included in this commit:
* `AlwaysSucceed` shows that plugins can be loaded
* `AlwaysThrowException` shows that exceptions are captured
* `ExpectPluginClassLoader` asserts that the
PluginClassLoader is active during static initialization.
These plugins are stored in the resources directory.
Each plugin has it's own source tree, and can have arbitrary code.
The plugins are compiled into class files in-place.
They are then packaged into a jar in a temporary file
which is deleted after the process exits.
This jar is then exposed for use in `plugin.path`, and tests
can access to the plugin class names through constants.
### Committer Checklist (excluded from commit message)
- [ ] Verify design and implementation
- [ ] Verify test coverage and CI build status
- [ ] Verify documentation (including upgrade notes)
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
> ServiceLoader fails when used from isolated plugin path directory
> -----------------------------------------------------------------
>
> Key: KAFKA-8340
> URL: https://issues.apache.org/jira/browse/KAFKA-8340
> Project: Kafka
> Issue Type: Bug
> Components: KafkaConnect
> Reporter: Chris Egerton
> Priority: Major
>
> Under some circumstances, the {{ServiceLoader.load}} mechanism will fail when
> used from an isolated plugin path directory and return an incomplete (often
> empty) {{ServiceLoader}} instance.
>
> To replicate:
> * Include a {{META-INF/services/...}} file in one of the JARS located in a
> plugin's directory with one or more implementations of that service listed
> inside. For the sake of example, let's say the name of this service is
> {{com.example.MyService}}
> * Program that plugin to invoke
> {{ServiceLoader.load(com.example.MyService.class)}}
> * Start the Connect framework, making sure this plugin is included on the
> plugin path and that it somehow invokes the {{ServiceLoader.load(...)}} method
> * Observe that the services loaded by that invocation do not include the
> ones described in the {{META-INF/services/...}} file contained in the JAR in
> the plugin's directory
>
> This is because the
> [ServiceLoader.load(Class)|https://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html#load(java.lang.Class)]
> method uses the current thread's context classloader to locate resources and
> load services. The current thread's context classloader is, in most cases, an
> instance of {{DelegatingClassLoader}}, which will (unless asked to locate
> resources corresponding to a provider-configuration file for a REST extension
> or config provider) simply delegate resource location to the parent and,
> unless asked to locate a class for a recognized plugin, also delegate class
> loading to the parent. Thus, none of the plugin's JARs are scanned for either
> provider-configuration files or for actual service classes.
> A viable workaround for some cases is to instead use the
> [ServiceLoader.load(Class,
> ClassLoader)|https://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html#load(java.lang.Class,%20java.lang.ClassLoader)]
> method, specifying the current class's classloader as the second argument.
> This causes the plugin's {{PluginClassLoader}}, which will scan all JARs in
> the plugin's directory to be used to locate resources and classes.
> However, this may not be feasible in all cases, especially when working with
> external libraries that may be difficult or impossible to apply this
> workaround on.
--
This message was sent by Atlassian Jira
(v8.3.2#803003)