摘要:JVM通过设立不同优先级和职责的加载器保证了类加载的安全性与灵活性,即双亲委派机制,但是实际生产中更复杂的需求又需要破坏双亲委派,即打破JVM约定过的类加载程序
目录
类的生命周期
类加载
加载
类加载器
双亲委派机制
总结
破坏双亲委派机制
类的生命周期
Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最 终形成可以被虚拟机直接使用的Java类型,这个过程被称作虚拟机的类加载机制。
类加载
加载
类的加载方式多种多样,可以通过网络,也可以通用代理、数据库、压缩文件等多种方式。
但加载阶段,JVM都需要完成三件事情
1)通过一个类的全限定名来获取定义此类的二进制字节流。
2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入 口。
类加载器
从JVM角度看只有两种类加载器,一种是启动类加载起 Bootstrap ClassLoader ,另一种是其他所有的类加载器。
这里类加载器之间的父子关系一般不是以继承(Inheritance)的关系来实现的,而是通常使用 组合(Composition)关系来复用父加载器的代码。
双亲委派机制
双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝加 载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的 加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请 求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。
总结
不同加载起负责的加载范围不一样。使用多个类加载器并采用双亲委派机制目的是确保类加载的层次关系和优先级,增强安全性与模块化。
单一类加载器无法实现这些功能。
安全性:比如类似java.lang.Obejct这样的核心类,限制必须使用启动类加载加载,确保不会被覆盖。这里使用特定加载器专门加载不可被覆盖的类(划分职责)。
而且因为委托机制,可以确保核心组件先加载。越基础、核心的类越先加载也可以保证基础类型一致性问题。
灵活性:不同加载器使用不同策略。
优先级和层次:划分了优先级,因为都会上抛,所以上面的加载器会先加载,且划分范围即有责任划分。这样做可以增强系统稳定性。
破坏双亲委派机制
Q:如果优先级最高最先被加载的类需要调用优先级最低最后被加载的类怎么办?
A:父类加载起发送请求让子类加载器加载
通过线程上下文类加载器,使用Thread的setContext-ClassLoader方法进行设置,即父类加载器请求子类加载器
Q:热部署热加载破坏双亲委派
A:以OSGi为例,通过更换类加载器做到。
OSGi 热部署通过每个模块(Bundle)拥有独立类加载器实现,允许动态更新模块而不重启系统。
更新时,OSGi 创建新类加载器加载更新后的类,并通过刷新包(Refresh Packages)更新依赖,确保新类可用。