Java 螺纹与x27之间的差异;s上下文类加载器和普通类加载器
线程的上下文类加载器和普通类加载器之间有什么区别Java 螺纹与x27之间的差异;s上下文类加载器和普通类加载器,java,multithreading,jvm,classloader,Java,Multithreading,Jvm,Classloader,线程的上下文类加载器和普通类加载器之间有什么区别 也就是说,如果Thread.currentThread().getContextClassLoader()和getClass().getClassLoader()返回不同的类加载器对象,将使用哪一个对象?每个类将使用自己的类加载器加载其他类。因此,如果ClassA.class引用了ClassB.class,那么ClassB需要位于ClassA的类加载器或其父类的类路径上 线程上下文类加载器是当前线程的当前类加载器。可以从classloader中的
也就是说,如果
Thread.currentThread().getContextClassLoader()
和getClass().getClassLoader()
返回不同的类加载器对象,将使用哪一个对象?每个类将使用自己的类加载器加载其他类。因此,如果ClassA.class
引用了ClassB.class
,那么ClassB
需要位于ClassA
的类加载器或其父类的类路径上
线程上下文类加载器是当前线程的当前类加载器。可以从
classloader
中的类创建对象,然后将其传递给ClassLoaderD
所拥有的线程。在这种情况下,如果对象希望加载其自己的类加载器上不可用的资源,则需要直接使用Thread.currentThread().getContextClassLoader()
。infoworld.com上有一篇文章解释了这一区别
=>
(一)
线程上下文类加载器提供
在教室的后门
授权计划
以JNDI为例:它的胆量是
由中的引导类实现
jar(从J2SE 1.3开始),但是
这些核心JNDI类可以加载JNDI
由独立供应商实施的供应商
供应商和可能部署在
应用程序的类路径。这
这个场景需要一个家长
类装入器(中的原始类装入器)
在这种情况下)加载对用户可见的类
它的一个子类装入器(
例如,系统一)。正常J2SE
授权不起作用,而
解决方法是制作核心JNDI
类使用线程上下文加载器,
从而有效地“隧道”通过
中的类加载器层次结构
与正确方向相反的方向
代表团
(2) 来自同一来源:
这种困惑可能会一直持续下去
Java已经有一段时间了。以任何J2SEAPI为例
动态加载任何资源
然后试着猜猜是哪种装载
它使用的策略。以下是一个样本:
- JNDI使用上下文类加载器
- Class.getResource()和Class.forName()使用当前的类加载器
- JAXP使用上下文类加载器(从J2SE1.4开始)
- ResourceBundle使用调用方的当前类加载器
- 通过java.protocol.handler.pkgs系统属性指定的URL协议处理程序仅在引导程序和系统类加载器中查找
- 默认情况下,Java序列化API使用调用方的当前类加载器
除了@David Roussel answer,类可以由多个类加载器加载 让我们了解它是如何工作的 摘自javin paul在爪哇的博客重温:
ClassLoader
遵循三个原则
授权原则
在需要时,用Java加载一个类。假设您有一个名为Abc.class的特定于应用程序的类,加载该类的第一个请求将到达application ClassLoader,application ClassLoader将委托给其父扩展ClassLoader,父扩展ClassLoader将进一步委托给Primordial或Bootstrap class loader
- 引导类加载器负责从rt.jar加载标准JDK类文件,它是Java中所有类加载器的父类。引导类装入器没有任何父类
- 扩展类加载器将类加载请求委托给其父级引导,如果不成功,则从jre/lib/ext目录或java.ext.dirs系统属性指向的任何其他目录加载类
- 系统或应用程序类加载器,它负责从CLASSPATH环境变量、-CLASSPATH或-cp命令行选项、JAR内清单文件的CLASSPATH属性加载特定于应用程序的类
- 应用程序类加载器是扩展类加载器的子类,它由
类实现sun.misc.Launcher$AppClassLoader
Java.lang.ClassLoader
实现的
可见度原理
根据可见性原则,子类加载器可以看到父类加载器加载的类,反之亦然
唯一性原则
根据这个原则,父类装入的类不应该再由子类装入器装入
这并没有回答最初的问题,但由于该问题对于任何
ContextClassLoader
查询都是高度排序和链接的,因此我认为回答应该何时使用context类加载器的相关问题是很重要的。简短回答:永远不要使用上下文类加载器!但是当您必须调用缺少ClassLoader
参数的方法时,将其设置为getClass().getClassLoader()
当一个类中的代码要求加载另一个类时,要使用的正确类加载器与调用方类是同一个类加载器(即,getClass().getClassLoader()
)。99.9%的时间都是这样,因为第一次构造新类的实例、调用静态方法或访问静态字段时
如果要使用反射创建类(例如反序列化或加载可配置命名类时),进行反射的库应始终通过从应用程序接收作为参数的类加载器来询问应用程序要使用哪个类加载器。应用程序(知道所有需要构造的类)应该传递它getClass().getClassLoader()
获取类加载器的任何其他方法都是不正确的。如果一个库使用了黑客,比如,或者它是由API中的缺陷引起的错误。基本上,Thread.getContextClassLoader()
的存在只是因为设计
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
// call some API that uses reflection without taking ClassLoader param
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}