Thread.setContextClassLoader 可以设置与 getCCL 返回的不同的 ClassLoader 吗?

Can Thread.setContextClassLoader set a different ClassLoader than returned by getCCL?

背景:

最近实现了一段代码,为特定的操作设置合适的ClassLoader,最后在操作完成后恢复原来的ClassLoader。

例如:

ClassLoader originalCL = Thread.currentThread().getContextClassLoader();
try {
    Thread.currentThread().setContextClassLoader(specialCL);
    // do operation here that requires 'specialCL'
} finally {
    Thread.currentThread().setContextClassLoader(originalCL);
}

根据 getContextClassLoader() 文档,返回 null 可能意味着两件事。 1) 系统 CL 或 2) 如果获取系统 CL 失败,bootstrap CL.

returns: the context ClassLoader for this Thread, or null indicating the system class loader (or, failing that, the bootstrap class loader)

根据 setContextClassLoader(Classloader cl) 文档,如果提供空 CL,则 1) 系统 CL 或 2) 如果设置系统 CL 失败,bootstrap CL。

cl - the context ClassLoader for this Thread, or null indicating the system class loader (or, failing that, the bootstrap class loader)


问题:

是否有可能使用上面的 try-finally-restore 编程模型,我最终会在 Thread 上得到一个与最初开始时不同的 ClassLoader?

例如:

// start out with System CL

ClassLoader original = getContextClassLoader(); // returns null

Thread.currentThread().setContextClassLoader(otherCL);

Thread.currentThread().setContextClassLoader(original); // i.e. set to null
// setCCL() tries to set System CL... fails 
// setCCL() tries to set Bootstrap CL... succeeds

反之亦然,我们从 Bootstrap CL 开始,当我们尝试使用 setContextClassLoader(null) 恢复时,系统 CL 得到恢复。这两种情况都可能吗?

不,当您将上下文 class 加载程序设置为 null 时,它只是设置为 null。因此它将继续使用它最初使用的任何 class 加载器。