Class SetContextClassLoader
- java.lang.Object
-
- jenkins.util.SetContextClassLoader
-
- All Implemented Interfaces:
AutoCloseable
public final class SetContextClassLoader extends Object implements AutoCloseable
Java defines aThread.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, becauseThread.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 preregisterClass
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 aClassLoader
, but you can overrideObjectInputStream.resolveClass(java.io.ObjectStreamClass)
to remove the need for guessing (asObjectInputStreamEx
in fact does).Alternatively, work around the problem by applying
SetContextClassLoader
liberally in atry
-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 viaSetContextClassLoader(Class)
. When the particular class loader needed is unclear,SetContextClassLoader(ClassLoader)
can be used as a fallback withPluginManager.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
Constructors Constructor Description SetContextClassLoader()
Change 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.SetContextClassLoader(ClassLoader cl)
Change theThread.getContextClassLoader()
associated with the current thread to the specifiedClassLoader
.
-
-
-
Constructor Detail
-
SetContextClassLoader
public SetContextClassLoader()
Change theThread.getContextClassLoader()
associated with the current thread to that of the calling class.- Since:
- 2.362
-
SetContextClassLoader
public SetContextClassLoader(Class<?> clazz)
Change theThread.getContextClassLoader()
associated with the current thread to that of the specified class.- Parameters:
clazz
- TheClass
whoseClassLoader
to use.- Since:
- 2.362
-
SetContextClassLoader
public SetContextClassLoader(ClassLoader cl)
Change theThread.getContextClassLoader()
associated with the current thread to the specifiedClassLoader
.- Parameters:
cl
- TheClassLoader
to use.- Since:
- 2.362
-
-
Method Detail
-
close
public void close()
- Specified by:
close
in interfaceAutoCloseable
-
-