Class SetContextClassLoader
- All Implemented Interfaces:
AutoCloseable
Thread.getContextClassLoader()
. Jenkins does not use this much; it will
normally be set by the servlet container to the Jenkins core class loader.
Some Java libraries have a fundamental design flaw, originating in premodular systems with a
"flat classpath", whereby they expect Thread.getContextClassLoader()
to have access to the
same classes as the class loader of the calling class. This fails in Jenkins, because Thread.getContextClassLoader()
can only see Jenkins core, not plugins.
It is a design flaw in the library if it fails to allow clients to directly specify a ClassLoader
to use for lookups (or preregister Class
instances for particular names).
Consider patching the library or looking harder for appropriate APIs that already exist. As an
example, ObjectInputStream
(used for deserializing Java objects) by default uses a
complicated algorithm to guess at a ClassLoader
, but you can override ObjectInputStream.resolveClass(java.io.ObjectStreamClass)
to remove the need for guessing (as ObjectInputStreamEx
in fact does).
Alternatively, work around the problem by applying SetContextClassLoader
liberally in
a try
-with-resources block wherever we might be calling into such a library:
class Caller { void foo() { try (SetContextClassLoader sccl = new SetContextClassLoader()) { [...] // Callee uses Thread.currentThread().getContextClassLoader() } } }
When called from a plugin, SetContextClassLoader()
should typically be used. This
implicitly uses the class loader of the calling class, which has access to all the plugin's
direct and transitive dependencies. Alternatively, the class loader of a specific class can be
used via SetContextClassLoader(Class)
. When the particular class loader needed is
unclear, SetContextClassLoader(ClassLoader)
can be used as a fallback with PluginManager.UberClassLoader
as the argument, though this is not as safe since lookups could be
ambiguous in case two unrelated plugins both bundle the same library. In functional tests,
RealJenkinsRule.Endpoint
can be used to reference a class loader that has access to the plugins
defined in the test scenario.
See the developer documentation for more information.
- Since:
- 2.362
-
Constructor Summary
ConstructorDescriptionChange theThread.getContextClassLoader()
associated with the current thread to that of the calling class.SetContextClassLoader
(Class<?> clazz) Change theThread.getContextClassLoader()
associated with the current thread to that of the specified class.Change theThread.getContextClassLoader()
associated with the current thread to the specifiedClassLoader
. -
Method Summary
-
Constructor Details
-
SetContextClassLoader
public SetContextClassLoader()Change theThread.getContextClassLoader()
associated with the current thread to that of the calling class.- Since:
- 2.362
-
SetContextClassLoader
Change theThread.getContextClassLoader()
associated with the current thread to that of the specified class.- Parameters:
clazz
- TheClass
whoseClassLoader
to use.- Since:
- 2.362
-
SetContextClassLoader
Change theThread.getContextClassLoader()
associated with the current thread to the specifiedClassLoader
.- Parameters:
cl
- TheClassLoader
to use.- Since:
- 2.362
-
-
Method Details
-
close
public void close()- Specified by:
close
in interfaceAutoCloseable
-