提问与回答之ClassLoader

来源:互联网 发布:js 计算时间间隔 毫秒 编辑:程序博客网 时间:2024/05/01 19:30

Q:

为什么自定义ClassLoader?

A:

1、加载网络资源等非系统类路径下的类
2、热部署


Q:

为什么改变类加载顺序?

A:

优先使用指定位置的类


Q:

为什么使用线程的ContextClassLoader?

A:

目前许多系统都是基于框架开发,框架一般都是由接口和缺省实现构成。在搭建框架时,只认识接口,并不清楚具体实现类的位置,但却要有脚手架代码,这时使用框架已知的ClassLoader来加载未来的实现类肯定是不现实的。因此必须要有一种机制,保证运行时告诉框架使用哪个ClassLoader,线程的ContextClassLoader就起这个作用。基于框架的系统运行时,在特定位置设置线程的ContextClassLoader,框架的脚手架代码从线程中取出ContextClassLoader使用。

现实中的实例很多:JNDI,JDBC,JAXP等。

JAXP:JAXP是java核心包中的类,JAXP用于使用一致的方式寻找具体的xmlParser实现类。JAXP主要用到两个类:javax.xml.parsers.SAXParserFactory和javax.xml.parsers.FactoryFinder,使用Bootstrap ClassLoader加载。SAXParserFactory使用newInstance产生SAXParserFactory具体类,具体类可能在系统类路径下,BootstrapClassLoader是看不到的,因此这时要使用ContextClassLoader来加载。

Q:

为什么出现ClassCastException?

A:

将A类型的对象作为B类型对象进行处理,我们称之为转型。转型可以在编译和运行时进行验证。

名词定义:
类型兼容:如果B类是A类本身,或者B类是A类的父类,或者B类是A类实现的接口类,那么我们称B类与A类兼容。
次第加载:假定B类和A类兼容,但B类不是A类本身,这时ClassLoader加载A类对象的话,在加载A类前,会首先加载B类。我们称A类次第加载B类。

下面根据“将A类型对象转型为B类型”的场景分别讨论一下编译时和运行时进行验证的过程:
1、编译时验证
如果B与A类不兼容,编译器就会提示“不能从A强制转型为B”。
2、运行时验证
运行时验证比较复杂,多种情况都可能会造成转型验证失败,而且验证失败会抛出ClassCastException异常。运行时一般在两种情况下会出现ClassCastException异常:
a、B类和A类不兼容
b、B类和A类兼容,但ClassLoader在加载A类对象时,会次第加载B类,这时再将A对象转型为B类时,如果两个B类是由不同的ClassLoader加载,将会抛出ClassCastException。
  一般情况下,只要B类和A类兼容,并且ClassLoader遵循双亲加载机制,那么将A类对象转型为B类时肯定会转型成功。


Q:

为什么默认使用双亲委托机制加载?

A:

第一个原因就是因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。 

第二个原因就是考虑到安全因素,我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时被加载,所以用户自定义类是无法加载一个自定义的 ClassLoader。







原创粉丝点击