为了账号安全,请及时绑定邮箱和手机立即绑定

线程上下文类装入器与普通类加载器的区别

线程上下文类装入器与普通类加载器的区别

一只甜甜圈 2019-07-19 10:48:16
线程上下文类装入器与普通类加载器的区别线程的上下文类装入器和普通的类加载器之间有什么区别?也就是说,如果Thread.currentThread().getContextClassLoader()和getClass().getClassLoader()返回不同的类加载器对象,将使用哪一个?
查看完整描述

3 回答

?
三国纷争

TA贡献1804条经验 获得超7个赞

每个类将使用自己的类加载器加载其他类。所以如果ClassA.class参考文献ClassB.class然后ClassB的类加载器的类路径上。ClassA或者它的父母。

线程上下文类加载器是当前线程的当前类加载器。中的类创建对象。ClassLoaderC然后传递给ClassLoaderD..在这种情况下,对象需要使用Thread.currentThread().getContextClassLoader()如果它希望加载它自己的类加载器上不可用的资源,则直接加载。


查看完整回答
反对 回复 2019-07-19
?
尚方宝剑之说

TA贡献1788条经验 获得超4个赞

这并不能回答原来的问题,但因为这个问题的排名很高,而且对任何一个问题都有关联。ContextClassLoader查询,我认为重要的是回答相关的问题,什么时候应该使用上下文类加载器。简短答覆:不要使用上下文类加载器。!但是把它设置为getClass().getClassLoader()当您必须调用缺少ClassLoader参数。

当一个类的代码请求加载另一个类时,要使用的正确的类加载器与调用方类相同。(即getClass().getClassLoader())。99.9%的情况是这样的,因为这就是jvm自己所做的。第一次构造新类的实例、调用静态方法或访问静态字段时。

当您希望使用反射(例如反序列化或加载可配置的命名类)创建类时,执行反射的库应该总是询问应用程序通过接收ClassLoader作为应用程序的参数。应用程序(它知道所有需要构造的类)应该传递它。getClass().getClassLoader().

获得类加载器的任何其他方法都是不正确的。如果库使用诸如Thread.getContextClassLoader()sun.misc.VM.latestUserDefinedLoader(),或sun.reflect.Reflection.getCallerClass()这是一个由API缺陷引起的错误。基本上,Thread.getContextClassLoader()存在的唯一原因是,无论是谁设计了ObjectInputStreamAPI忘记接受ClassLoader作为一个参数,这个错误至今一直困扰着Java社区。

也就是说,许多JDK类使用少数几个黑客中的一个来猜测要使用的类加载器。有些人使用ContextClassLoader(当您在共享线程池上运行不同的应用程序时,或者当您离开ContextClassLoader null),有些人在堆栈中行走(当类的直接调用者本身是一个库时,堆栈就会失败),有些人使用系统类装入器(这很好,只要文档中只使用CLASSPATH)或者引导类加载器,并且有些使用上述技术的不可预测的组合(这只会使事情变得更加混乱)。这导致了大量的哭泣和咬牙切齿。

当使用这样的API时,首先,尝试查找接受类加载器作为参数的方法的重载。..如果没有合理的方法,请尝试将ContextClassLoader在API调用之前(然后重新设置它):

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);}


查看完整回答
反对 回复 2019-07-19
  • 3 回答
  • 0 关注
  • 1162 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信