Class.getClassLoader() 和 Thread.getContextClassLoader() 有什么区别?
Class.getClassLoader() 和 Thread.getContextClassLoader() 有什么区别?
根据这个线程:
Class.getClassLoader()
返回加载调用它的类的ClassLoader
。
Thread.getContextClassLoader()
返回为Thread
设置的上下文ClassLoader
,如果Thread
的setContextClassLoader(ClassLoader)
方法被调用,则该ClassLoader
可以与加载Thread
类本身的ClassLoader
不同。这可用于允许启动线程的对象指定运行在该线程中的对象应使用的
ClassLoader
,但需要某些对象的协作才能使其正常工作。
因此,如果您想知道为什么有3个API调用
Thread<instance>.getContextClassLoader()
Thread<instance>.getClassLoader()
Class<instance>.getClassLoader()
在《Find a way out of the ClassLoader maze》中,您可以找到答案。
首先,为什么需要线程上下文类加载器?它们在J2SE中默默无闻地被引入。Sun Microsystems缺乏适当的指导和文档,这也解释了为什么许多开发人员会感到困惑。
实际上,上下文类加载器提供了一个绕过J2SE中引入的类加载委派机制的后门。通常,JVM中的所有类加载器都按层次结构组织,因此每个类加载器(除了引导整个JVM的原始类加载器)都有一个父类加载器。
[...]
更糟糕的是,某些应用程序服务器将上下文和当前类加载器设置为不相关的ClassLoader实例,这些实例具有相同的类路径,但不是委托关系的父子关系。
Class.getClassLoader()返回用于加载特定类的类加载器。
Thread.getContextClassLoader()获取设置为线程上下文的ClassLoader,该ClassLoader将被用于加载所需的类。
例如,在Tomcat中会有所不同。对于java.lang.String,类加载器将是顶级JVM类加载器,该加载器不会在您的类路径中拥有所有类,但是线程上下文类加载器应该会这样做。