天天看点

深入理解JVM(三)--------------------------虚拟机类加载机制

写这篇博客的目的是为了对已学过的知识做一下笔记总结,如果想要从这篇文章中得到一些与众不同的理解,那么可能要让各位失望了。

类从被加载进虚拟机内存中开始,到卸载出内存为止,他的整个生命周期包括:加载----验证----准备----解析-----初始化----使用-----卸载

深入理解JVM(三)--------------------------虚拟机类加载机制

1、加载阶段

加载阶段有三件事情:

1)通过一个类的全限定名来获取定义此类的二进制字节流

2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构

3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据结构

2.验证阶段

验证阶段的目的是为了确保class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全

3.准备阶段

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段。这些变量所使用的内存都将在方法区中进行分配。这时候进行内存分配的仅包括类变量(被static修饰的变量),而不包括实例变量,实例变量会在对象实例化时随着对象一起分配在JAVA堆中,这里所说的初始值通常指数据类型的默认值,比如零值。要与初始化阶段的赋值区别开来

4.解析阶段

解析阶段是虚拟机将常量池内的符号引用替换成直接引用的过程

5.初始化阶段

初始化阶段实际上是执行类构造器<clinit>()方法的过程,而这个<clinit>()方法是由编译器自动收集类中的所有类变量的赋值操作和静态语句块中的语句产生的,而编译器收集的顺序是由语句在源文件中出现的顺序决定的

初始化阶段会根据程序员通过程序指定的值去初始化类变量和其他资源

三。双亲委派模型

类加载阶段中的“通过一个类的全限定名来获取定义此类的二进制字节流”的动作放在虚拟机外部实现,以便让应用程序决定如何去获取所需要的类,实现这个动作的代码模块称为”类加载器“

对于任意一个类,都需要由加载它的类加载器和这个类本身一同确定其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。

有以下三种系统提供的类加载器:

(1)启动类加载器

(2)扩展类加载器

(3)应用程序类加载器

深入理解JVM(三)--------------------------虚拟机类加载机制

双亲委派模型的工作机制是:如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定的类时(即

ClassNotFoundException

),子加载器才会尝试自己去加载。

优点:(1)使用双亲委派模型的好处在于Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存在在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的Bootstrap ClassLoader进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,那系统中将会出现多个不同的Object类,程序将混乱。因此,如果开发者尝试编写一个与rt.jar类库中重名的Java类,可以正常编译,但是永远无法被加载运行。

(2)能够提高软件系统的安全性,在此机制下,用户自定义的类加载器不可能加载本应该由父类加载器加载的可靠类

继续阅读