在讲类的加载过程之前,我们先聊聊什么是JVM?
我们知道Java最大的一个优势,就是跨平台。可以通过一次编译,到处执行。同一份代码,可以在Window、Linux、Mac这些不同的操作系统执行。
Java能做到这一点,就是因为JVM的存在。
在JVM获取到编译好的Java字节码(.class文件)之后,会经过几个步骤:
1、加载:首先会将这些.class文件存入方法区(“方法区”是JVM内存模型种,内存的其中一块区域,主要存放运行期间的常量池、静态变量、类信息等数据)。
2、验证/准备/解析/初始化:这一步骤,其实我们程序开发不需要关心这部份,我查了很多博文,对这部分的解释,都大同小异,所以我将这部分汇总来讲。其实这部分所做的工作,就是对class文件的字节流进行合法性校验,验证通过后;在“准备”阶段,会对static的静态变量分配内存并初始化,初始化是指设默认值,通常是0或者null的形式;然后在“解析”阶段,会对常量池(第一步加载存入方法区的数据)的数据做解析,将符号引用转换为直接引用;最后就是初始化,完成整个类的加载,如果有父类,会先加载父类。到了这一步骤,这个阶段就算是执行完成了。
3、分配内存:在完成类的加载到内存,并完成验证/解析/初始化等过程后,这个类就已经做好准备了,等待一个对象的产生与引用。当这个对象产生时,JVM就会为这个对象在内存中开辟一块空间,当这个对象被引用时,JVM的就会对这个对象引用计数器数量加1。
4、卸载:当这个对象不再被其他对象所引用时,这个对象也就在程序中失去了意义,JVM就会将其回收掉。回收的一个重要的判定标准就是引用计数器的个数是否为0。
对于内存的分配与回收,会涉及到JVM的内存结构、堆内存分区、未被回收的对象在各个分区之间的流转,以及当对象消亡时JVM采用的垃圾回收算法。
这些会是我们程序开发以及线上生产排查问题时的要点。
对于类加载过程,了解在加载过程中将类信息存入方法区,经过验证/解析/初始化等一系列工作后,完成类的加载。直至一个对象的产生或者引用,JVM开辟空间、分配内存,直到该对象不再被持有,被JVM回收。