Thread.currentThread().getContextClassLoader()
阅读原文时间:2021年04月20日阅读:1

Thread线程API中,getContextClassLoader()方法的描述为:

* Returns the context ClassLoader for this Thread. The context
* ClassLoader is provided by the creator of the thread for use
* by code running in this thread when loading classes and resources.
* If not {@linkplain #setContextClassLoader set}, the default is the
* ClassLoader context of the parent Thread. The context ClassLoader of the
* primordial thread is typically set to the class loader used to load the
* application.
*
*

If a security manager is present, and the invoker's class loader is not
* {@code null} and is not the same as or an ancestor of the context class
* loader, then this method invokes the security manager's {@link
* SecurityManager#checkPermission(java.security.Permission) checkPermission}
* method with a {@link RuntimePermission RuntimePermission}{@code
* ("getClassLoader")} permission to verify that retrieval of the context
* class loader is permitted.

翻译成中文大概意思为:

返回该线程的ClassLoader上下文。线程创建者提供ClassLoader上下文,以便运行在该线程的代码在加载类和资源时使用。如果没有,则默认返回父线程的ClassLoader上下文。原始线程的上下文 ClassLoader 通常设定为用于加载应用程序的类加载器。

首先,如果有安全管理器,并且调用者的类加载器不是 null,也不同于其上下文类加载器正在被请求的线程上下文类加载器的祖先,则通过 RuntimePermission("getClassLoader") 权限调用该安全管理器的 checkPermission 方法,查看是否可以获取上下文 ClassLoader。

下面的例子说明子线程的ClassLoader与父线程的一致:

public class Test {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getId()+"-outer:"+Thread.currentThread().getContextClassLoader());
        new Thread(){
            public void run(){
                System.out.println(Thread.currentThread().getId()+"-inner:"+Thread.currentThread().getContextClassLoader());
            }
        }.start();
        new Thread(){
            public void run(){
                System.out.println(Thread.currentThread().getId()+"-inner:"+Thread.currentThread().getContextClassLoader());
            }
        }.start();
    }
}

 返回值:

1-outer:sun.misc.Launcher$AppClassLoader@18b4aac2
12-inner:sun.misc.Launcher$AppClassLoader@18b4aac2
13-inner:sun.misc.Launcher$AppClassLoader@18b4aac2

以上结果表示返回的ClassLoader是一样的。

应用:

在阅读org.apache.commons.beanutils.BeanUtils#copyProperties源码时,发现里面用到了类org.apache.commons.beanutils.ContextClassLoaderLocal,该类中的map让ClassLoader作为key,通过以上的描述,在一个JVM程序中,得到的ClassLoader是一个,所以可以作为一个全局的key存在。