第七章:虚拟机类加载机制
Java类的生命周期
-
加载:将class文件加载进虚拟机内存。
-
验证:为了保证class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
-
准备:正式为类变量分配内存并设置类变量初始值。这些变量都在方法区分配。这里的初始值是java默认的初始值(Java为每个基本类型设置了默认的零值,这也是类变量无需初始化就有值,而局部变量没有的原因),变量的真正赋值要在初始化阶段。
-
解析:将常量池内的符号引用替换为直接引用。
-
初始化:开始真正执行类中定义的Java程序代码。根据程序员通过程序定制的主观计划去初始化类变量和其他资源,即为赋予变量程序员定义的值。
-
使用
-
卸载
类加载器
-
通过一个类的全限定名来获取此类的二进制字节流,这个动作的代码模块成为“类加载器”。
-
比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义。即使两个类来自同一个class文件,只要加载它们的类加载器不同,那这两个类就必定不相等。
-
3种系统提供的类加载器
-
启动类加载器:用来加载<JAVA_HOME>/lib目录下或被-Xbootclasspath参数指定的路径的类库。
-
扩展类加载器:加载<JAVA_HOME>/lib/ext目录的类库。
-
应用程序类加载器:负责加载用户类路径上所指定的路径。即开发时导入的第三方jar包。
-
它们三个从上向下为继承关系。
-
双亲委派模型
-
具体工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一层次的类都是如此,因此最终所有的请求都会传送到顶层的启动类加载器,只有当父类加载器无法加载请求时,子类加载器才会尝试加载。
-
原因:确保同一个类由同一个类加载器完成,如果各个类加载器自行加载,那系统中可能会出现多个不同的Object类(不同类加载器加载的类一定不相等)。
-
双亲委派模型的破坏:
-
双亲委派模型在JDK1.2才出现,所以双亲委派模型不得不做一些妥协(为了兼容)。
-
有时候基础类可能会调用用户自己实现的类。例,JNDI需要调用独立厂商部署在类路径下的代码,而启动类加载器并不认识这些独立代码,所以Java设计团队只能引入了一个:线程上下文加载器,这就出现了父加载器请求子类加载器去完成类加载的动作,破坏了模型。其实JDBC、JCE、JAXB等都是这种方式。
-
用户为了追求程序的动态性。例,OSGi实现模块化热部署的关键就是它自定义的类加载机制的实现,OSGi的类加载器并不符合双亲委派模型。
-