如何识别垃圾?
引用计数法:对象每被引用一次,就在该对象的对象头加上一次引用次数,如果引用次数为0,则此对象可以回收
可达性算法:以GC Root的对象为起点,如果相关对象不在任意一个以GC Root为起点的引用链中,则会被回收。
发生GC的时候,会先判断对象是否执行了finalize方法,如果没有则先执行finalize方法,(在这个方法中对象还有一次逃出死亡的机会,如果跟GC Root关联起来就不会被清理)执行finalize方法之后,再判断对象是否可达,不可达则回收。
finalize方法只会被执行一次,也就是只有一次机会,以后再被GC会直接回收,不再进入finalize。
GC Root有哪几类?
虚拟机栈中引用的对象
本地方法栈INJ引用的对象
方法区中类静态属性引用的对象
方法区中常量应用的对象
垃圾回收的方法:标记清除法,复制算法,标记整理法,
对象晋生老年代:
1.次数超过15(默认)
2.大对象,减少开销
3.在S区中相同年龄的对象大小之和大于空间一半以上,则年龄大于该年龄的对象也会晋升到老年代
Stop The World
GC的时候会触发STW,只有垃圾回收器线程在工作,其他工作线程被挂起。
Full GC导致的STW会更长,所以要尽可能避免对象过早进入老年去,尽可能晚的触发FullGC
新生代和老年代空间大小1:2也是这个原因
因为Full GC影响性能,一般要选择合适的时机进行,也就是safa Point
safe Point:循环的末尾
方法返回前
调用方法的call之后
抛出异常的位置
垃圾收集器种类
新生代: Serial ParNew Parallel Scavenge
老年代: Serial Old CMS Parallel Old
通吃:G1
Serial:单线程的垃圾回收器
ParNew:上面的多线程版本(复制算法)减少了STW的时间,只有它能和CMS收集器配合工作
Parallel Scavenge:和上面的差不多,能控制最大垃圾回收时间参数和直接设置吞吐量大小
Serial Old:工作在老年区的单线程的垃圾回收器
Parallel Old:多线程,也是吞吐量优先
CMS:以实现最短STW为目标的收集器,并发收集器,垃圾收集器线程和用户线程同时工作
采用标记清除法,有四个步骤: 初始标记:(STW)只标记GC Root关联的对象
并发标记:GC Root Tracing,找出不可达的对象
重新标记 :(STW)修正并发标记中有一些重新被引用了的对象
并发清除:
CMS三个缺点:1.吞吐量比较低
2.无法处理浮动垃圾,清理的同时有新的垃圾产生,得等到下一次GC,也就是得留下足够的空间确保线程正常运行
3.标记清除法,大量内存碎片
G1:1.和CMS一样,并发收集器
2.整理控件空间更快
3.不会牺牲大量的吞吐性能
4.不需要更大java 堆空间
5.需要GC停顿时间更好预测
对比CMS:1.不会产生内存碎片,G1从整体上看是标记整理法,局部上是复制算法,都不会产生内存碎片
2.可以设定停顿时间
G1各代的存储地址不是连续的,每一代都使用了n个不连续的大小相同的Region,除了新老生代,还有个H区,放大对象,防止反复拷贝移动。
可以根据价值大小维护一个优先列表,优先收集回收价值的Region,避免了整个老年代的回收,减少了STW
初始标记,并发标记,最终标记,筛选回收