【 java 虚拟机知识 第二篇 】
目录
1.类初始化和类加载
1.1.创建对象的过程
1.2.对象的生命周期
1.3.类加载器
1.4.双亲委派模型
1.5.类加载的过程
2.垃圾回收
2.1.垃圾回收介绍
2.2.触发垃圾回收的方式
2.3.判断垃圾的方法
2.4.垃圾回收算法
2.5.垃圾回收器
2.6.minorGC、majorGC、fullGC
2.7.CMS与G1的区别
1.类初始化和类加载
1.1.创建对象的过程
分为四步:类加载检查,分配对象内存空间,初始化零值操作,进行必要设置(对象头),执行init方法
类加载:java虚拟机在执行到new关键字的时候,会先进行对应类的类是否加载,如果没有加载,那么就会先执行类加载,然后再执行new关键字
分配内存空间:在堆中分配一段空间给对应对象
初始化零值操作:给对象的空间内的对应成员初始化为零值(对象头除外)
进行必要的设置:比如说:给对象头设置一些信息,类的元数据,对象的年龄,对象的哈希码
执行init方法:执行对应的构造方法
1.2.对象的生命周期
对象的生命周期:创建,使用,销毁
创建:上面的部分
使用:比如说调用该对象的成员
销毁:该对象没有被引用了,那么就会被看作垃圾进行回收
1.3.类加载器
类加载器:启动类加载器,扩展类加载器,应用程序类加载器
启动类加载器:加载java核心库里面的类
扩展类加载器:加载一些扩展的类,比如说框架的类
应用程序类加载器:加载用户自己手动创建的类
1.4.双亲委派模型
原则:
- 向上委派
- 向下加载
如果一个类加载器收到了加载类的任务,不会自己先执行,而是往上委派给自己的父类,依次类推,直到委派给最终的父类也就是启动类加载器,然后从启动类加载器开始,判断该类是否被自己加载,是否能进行加载,如果能直接返回及即可,如果不能继续往下加载(抛给子类),依次类推
作用:
1.保证类的唯一性
向上委派,向下加载的这种方式,保证了一个类不会被重复加载,并且保证的一个类只会被一个类加载器加载
2.保证安全性
如果用户自己编写了一些类,类的全限定名与Java核心库中的类一致,可能会出现优先加载用户的类,从而间接导致核心类被用户修改了,那么通过向上委派,向下加载的这种方式从上开始加载,保证了类的安全性
3.形成了隔离和分层的效果
不同的类加载器负责不同的类,既不会重复加载,而保证了高效性
4.简化了类加载流程
向上委派,向下加载的这种方式,保证了一个类只能加载一次并且不同的类加载器负责不同的类,从而简化了流程
1.5.类加载的过程
从大体上类加载分为五步:类加载,连接,初始化,使用,卸载
细分又有七步:类加载,验证,准备,解析,初始化,使用,卸载
类加载:通过类的全限定名找到对应的二进制字节码文件,将该文件转换到内存形成创建对象实例的模板
验证:验证该二进制字节码是否符合jvm规范,比如说校验魔术,主版本号等等,具体由:文件格式校验,元数据验证,字节码验证,符号引用验证
准备:给该类的静态变量赋一些初始化值
解析:将原来的符号引用转为直接引用
初始化:执行构造器方法,执行父类的静态成员,子类的静态成员,父类的构造方法,子类的构造方法
使用:自己用户使用
卸载:判断该类没有被引用即可卸载,三个方面看
- 该类里面的所有的实例对象都已经被回收了
- 该类的classLoder对象已经被回收了
- 该类的实例没有被引用
2.垃圾回收
2.1.垃圾回收介绍
以前传统的开发人员他需要进行一个对内存的手动释放,而垃圾回收就是可以自动的对内存进行回收,它既提高了开发效率,也避免了一些问题(内存溢出,内存泄漏)
2.2.触发垃圾回收的方式
方式:内存不足,手动执行,jvm调参,垃圾回收器自己的内部策略
1.内存不足:当内存不足的时候,会触发直接垃圾回收机制
2.手动执行:自己开发人员自己手动指定执行
3.jvm调参:通过调参可以来指定垃圾回收的行为
4.内部策略:垃圾回收内部可能指定了创建对象的数量和内存使用情况,如果超过一定的阈值就会触发垃圾回收
2.3.判断垃圾的方法
方法:引用计数法,可达性分析法
引用计数法:
给每次对象分配一个计数器,如果该对象被一个对象引用,那么就会将计数器进行加一,如果该对象没有被引用,那么此时计数器为0,则被判断为可以被回收
可达性分析法:
从GC Root出发找对应对象进行标记,如果有一个对象没有被标记(代表没有被直接引用或间接引用)那么该对象可以被回收,GC Root对象:Java的核心库类,调用本地方法的类,活跃线程的类
2.4.垃圾回收算法
垃圾回收算法:标记清除算法,标记整理算法,复制算法
标记清除算法:对引用的对象进行标记,然后进行清除(不是真正的清除,而是记录其对象的起始地址和结束地址到一个地址表中,下次要添加新对象时会先从表中找,找到一个适合大小的就会进行覆盖),清除:记录地址,新对象进行覆盖,好处:速度快,缺点:内存碎片化严重(内存不连续了,本来可以存入的对象存入不了)
标记整理算法:同理进行标记,然后再对可存活对象进行整理,最后清除,好处:避免了内存碎片化问题,缺点:速度慢
复制算法:将内存空间分为两份,一份存对象from,一份为空to,当要回收时,复制可存活对象移入为空的内存空间to中(移入既整理),然后对存对象的空间from整体清除,然后名称from和to换过来,好处:避免了内存碎片化问题,缺点:内存使用率不高
2.5.垃圾回收器
根据作用范围:
新生代:Serial,ParNew,Parallel Scavenge,都是使用的复制算法
老年代:Serial Old(标记整理),CMS(标记清除),Parallel Old(标记整理)
整个堆:G1(整体标记整理,细分区域使用复制)
Serial GC:串行的收集器
ParNew/CMS:并行的收集器,重响应时间快的特点
Parallel GC:并行的收集器,重吞吐量高的特点
G1:并行的收集器,比较平衡
2.6.minorGC、majorGC、fullGC
minorGC:
- 范围:作用于新生代
- 作用时机:当新生代的伊甸园区的空间无法装入新创建的对象时,就会触发一次minorGC,并且每触发一次minorGC,其存活对象的年龄加一
- 细节:作用时间短,次数多
majorGC:
- 范围:作用于老年代
- 作用时机:当新生代的对象需要移入老年代时,发现其空间不足,那么就会触发majorGC
- 细节:作用次数不多,而不常使用
fullGC:
- 范围:作用于整个堆
- 作用时机:当新生代对象需要移入老年代时,发现其空间不足,会触发minorGC,触发之后,如果还是老年代空间不足,那么就会触发fullGC,对整体进行整理
- 细节:作用次数不多,作用时间长
2.7.CMS与G1的区别
方面:作用范围,STW的时间,垃圾回收过程,内存碎片化,浮动垃圾
作用范围:
CMS作用于老年代
G1作用于整个堆
STW的时间:
CMS是重响应时间快的,STW的时间会更短
G1可以对STW时间进行一个可预测的操作
内存碎片化:
CMS使用的是标记清除算法,会造成内存碎片化问题
G1使用的是标记整理算法,不会造成内存碎片化问题
垃圾回收过程:
CMS过程:初始标记,并发标记,重新标记,并发清理
G1过程:初始标记,并发标记,最终标记,筛选回收(如果并发标记中出现了对象引用改变,会将其对象引用存入一个队列中,直到最终标记时从队列进行进一步的筛选)
浮动垃圾:
CMS:它使用的是并发清理,那么如果垃圾回收的速度低于产生垃圾的速度,那么就会出现问题,从而导致CMS转变为Serial,并且也由于在回收的过程中会产生一些浮动垃圾,因此需要一部分空间来存储对应的浮动垃圾
G1:它虽然也会产生垃圾,但是不会出现该问题 ,并且它是使用的多个垃圾回收器进行垃圾回收,效率更高