为什么setContextClassLoader()
方法放在Thread
?
什么不同的线程有不同的类加载器?
问题是如果我扩展了一个ClassLoader
,加载了一些新的类。到我的自定义类加载器。
现在,我希望它是上下文类加载器,所以我调用方法Thread.currentThread().setContextClassLoader(loader)
。
这些新类是否仅在当前线程的上下文中可用?或者它是如何工作的?
谢谢
Context类加载器是线程将用于查找类的类加载器。在编写应用程序服务器或类似的东西时,您主要关心这一点。我们的想法是,您可以从应用程序服务器的类加载器中加载的类启动一个线程,然后传递一个子类加载器来处理加载已部署应用程序的类。
线程上下文类加载器有点像黑客。
使用反射加载类时,可以使用显式类加载器或直接调用类。使用普通Java代码链接到类时,请求链接的类用作加载器的源。
Thread.setContextClassLoader
用于为Thread.getContextClassLoader
设置类加载器。随机API(特别是通过ServiceLoader
)使用它来通过反射获取类,以便您可以更改实现。根据你的代码改变实现,取决于它在关键时刻运行的线程是一个坏主意。
Thread.setContextClassLoader
is用于设置contextClassLoader,如果没有手动设置,它将设置为systemClassLoader,这是Launcher.AppClassLoader
,这可以通过检查Launcher的源代码来证明。
那么contextClassLoader的用途是什么?
contextClassLoader提供了围绕类加载委派方案的后门。
然后这个问题成为我们为什么需要这个后门?
来自JavaWorld的文章Find a way out of the ClassLoader maze
以JNDI为例:它的内容由rt.jar中的引导类实现(从J2SE 1.3开始),但这些核心JNDI类可以加载由独立供应商实现并可能部署在应用程序的-classpath中的JNDI提供程序。此方案要求父类加载器(在本例中为原始类加载器)加载对其子类加载器之一可见的类(例如,系统类)。正常的J2SE委派不起作用,解决方法是使核心JNDI类使用线程上下文加载器,从而在与正确委托相反的方向上有效地“隧穿”通过类加载器层次结构。
Java类加载器可以分为以下类别
1)Bootstrap类加载器 从JAVA_HOME / jre / lib / rt.jar加载类
2)扩展类加载器< 从JAVA_HOME / jre / lib / ext加载类
3)系统类加载器 应用程序的类路径
我们可以创建自己的类加载器并指定可以加载类的自己的位置,即引用ContextClassLoader
希望能够了解我们为什么需要使用setContextClassLoader()