垃圾回收期与内存分配策略
2020-02-26 15:07:47 0 举报
AI智能生成
深入理解jvm虚拟机第二章--垃圾回收
作者其他创作
大纲/内容
2.垃圾回收算法
标记-清除 算法
原理
首先标记出需要回收的对象,然后统一回收所收集的对象
优点
最基础的算法
缺点
效率比较低
空间问题:会产生大量的碎片空间,导致大的对象无法使用
复制算法
原理
它将可用的空间划分为大小相等的两块,每次只使用一块,当一块内存用完了,就将还用着的
对象复制到另一块上,然后再把已使用过的空间一次清理掉
对象复制到另一块上,然后再把已使用过的空间一次清理掉
优点
实现简单,运行高效
缺点
将内存缩小为原来的一般,代价太高
特点
很多虚拟机都是使用这种收集算法来回收新生代
Eden:survivor = 8:1
标记-整理算法
原理:
让所有存活的对象都向一端移动,然后清理掉边界以外的内存
分代收集算法
原理
根据对象存货周期的不同划分危机快:新生代和老年代。新生代每次垃圾收集都发现大批对象死去,
采用复制算法,老年代采用标记清理或者标记整理算法
采用复制算法,老年代采用标记清理或者标记整理算法
4.垃圾回收器
serial 收集器
特点
单线程
需要暂停所有的用户线程
简单高效,单线程收集效率高,在client模式下比较好
收集过程
1.新生代采用复制算法,暂停所有的用户线程
2.老年代采用标记-整理算法,暂停所有用户线程
ParNew 收集器
就是serial的多线程版本
收集过程
新生代多线程的采用赋值算法
老年代采用标记-整理算法
Paraller Scavenge 收集器
一个注重吞吐量的收集器
吞吐量:运行用户代码的时间/(运行用户代码时间+垃圾收集时间)
-XX:+UseAdaptiveSizePolicy
虚拟机根据运行情况自动调整Eden,survivor的比例
Serial Old 收集器
srerial的老年代版本,用的标记整理算法
Paraller old收集器
Paraller Scavenge的老年版本
替代了serial old收集器,提升了老年代垃圾收集的效率
CMS收集器
concurrent mark sweep
是一种获取最短回收停顿时间为目的的收集器
步骤
初始标记
需要停顿,仅仅关联GC ROOT能关联的对象
并发标记
并发操作,主要的标记过程,时间略长
重新标记
需要停顿,主要是标记在并发标记时间内变化的对象
并发清除
并发操作,清除过程
缺点
CMS收集器催cpu资源非常敏感,默认启动的线程数是(cpu+3)/4
CMS收集器无法处理浮动垃圾
浮动垃圾:在并发清理期间产生的垃圾
应对策略:留一定的空间,到达一定的阈值就开始清理
如果清理期间内存不够了咋办,老年代采用serial old收集器
基于标记清除算法,有内存碎片化的缺点
-XX:+UseCMSCompactAtFullColleation
全量垃圾收集的时候进行整理
-XX:+CMSFullGCsBeforeCompaction
运行多少次FullGc执行一次整理过程
G1收集器
garbage first
特点
并行与并发
利用多cpu,多线程的硬件优势,将其他收集器需要停顿的时间尽量并发完成
分代收集
空间整合
整体上看是标记整理,region之间是复制
可预测的停顿
步骤
初始标记
初始标记和GC ROOT直接关联的对象,且修改TAMS的值,让下一个用户创建的对象在这个region内
并发标记
需要停顿,对对象进行可达性分析,标记
最终标记
标记处在并发标记阶段产生的垃圾对象
筛选回收
对比各个region的回收价值和成本,在用户期望的回收时间内回收最多的垃圾
理解GC日志
GC发生的时间
停顿类型:full是要stop-the-world
发生的区域,和收集器的名字密切相关
3324k->152k(3712k)
qc前该区域已使用容量->gc后该区域已使用容量(该区域总容量)
time:user=0.01 sys=0.00,real =0.02 secs
用户态消耗的时间,内核态消耗的时间,从开始到借宿虽经过的墙钟时间
1.对象死了吗
引用计数算法
原理:给对象天机一个计数器,有人引用就加1,去掉引用就减1,为0的就是没有被引用的对象
特点:解决不了循环引用的问题
可达性分析算法
原理:通过GC ROOT的对象作为七点,从这些节点开始向下搜索,搜索所走的路径叫做引用链,
从一个对象到GC ROOT没有引用链就说明这个对象没用了。
从一个对象到GC ROOT没有引用链就说明这个对象没用了。
特点:
GC ROOT
虚拟机栈中引用的对象
方法区中静态属性的对象
方法区中常量引用的对象
本地方法栈引用的对象
再谈引用
强引用
Object obj = new Object()
不会被回收
软引用
有用但不是必须得对象,在内存溢出之前会被二次回收
SoftRefrence
弱引用
非必须对象,发生垃圾收集就会被回收
weakRefrence
虚引用
幽灵引用或者幻影引用。会被回收
phantomRefrence
生存还是死亡
判断一个对象真正死亡
1.如果对象可达性分析之后发现没有雨GC-ROOTS相连的引用链,那它将会被第一次标记并且进行一次筛选
,筛选条件是 对象是否有必要执行finalize方法
,筛选条件是 对象是否有必要执行finalize方法
2.如果没有必要执行finalize时,就会被下一次垃圾回收回收。
3.如果有必要执行finalize方法,就会被放入F-queue对俩值中,finalize方法是对象最后的机会,只有在这个方法中自己和引用链上的任何对象有关联,就会被移除“即将回收”的集合。
回收方法区
无用的类
该类的所有势力都已经被回收,也就是java堆中不存在该类的任何实例
加载该类的classLoader已经被回收
该类对应的java.lang.class对象没有在任何对象被引用,无法在任何地方通过反射访问该类的方法
参数控制
-Xnoclassgc
-verboise:class
-XX:+TrancsClassLoading -XX:+TranceClassUnLoading
3.hotspot的算法实现
枚举根节点
GC进行时必须停顿掉所有的java执行线程,stop the world
hotspot采用一组称为Oop的数据结构来达到这个目的
安全点
在特定位置记录Oop,这些点就是安全点
是否具有让程序长时间执行的特征
方法调用,循环跳转,异常跳转
如何让线程都到安全点上
抢先式中断
主动式中断
安全区域
在一段代码片段中,引用关系不会发生变化
线程sleep
内存分配及回收策略
对象优先在eden分配
对象优先在eden区,空间不够执行minor gc
大对象直接进入老年代
大对象
很长的字符串和数组,需要大量的连续空间
-XX:PretenureSizeThreshold:大于这个数的直接进入老年代,避免eden和survivor区域复制
长期存活的对象直接进入老年代
对象年龄计数器
-XX:MaxTenuingThreshold 大于多少岁晋升到老年代,默认15岁
动态对象年龄判定
如果在survisor区域内相同年龄的所有对象大小总和大于总量一半,就把这个年龄及以上的全部进入老年代
空间分配担保
发生minorGc之前,会检查老年代的最大可用空间是否大于新生代的所有对象总空间,如果不够会看是否可以担保,如果可以,才会进行回收
0 条评论
下一页