GC 垃圾收集器
垃圾收集器(Garbage Collection)
垃圾收集器Garbage Collection简称GC。作为守护线程运行,自动划地对内存空间进行清理,避免内存泄露的问题。
在JVM虚拟机的内存中,程序计数器、虚拟机栈和本地方法栈都是随线程而生,随线程而灭的,栈帧随着方法的进入和退出做压栈和弹栈的操作,实现了自动的内存清理。因此,垃圾的回收工作主要集中在堆和方法区中,在程序运行期间,这部分内存是线程共享的,它们的分配和使用都是动态的。在堆内存中废弃的对象,和方法区中废弃的常量和类都会被GC回收。
垃圾判断机制
类
满足以下三个条件:
1.加载类的ClassLoader已经被回收。
2.该类的所有实例对象都已经被回收。
3.该类的Class对象没有在任何地方被引用,也就是说无法通过反射机制访问该类。
对象
引用计数器
具体实现:
每当被一个引用指向时,计数器就会+1,而当一个引用不再指向它时,计数器就-1,当计数器为0时,表示对象已经废弃。缺点是:每当被引用或不再被引用时,计数器都要修改其计数,称为footprint,这会给整个程序的性能带来很大的影响。并且,引用计数器不能解决对象间循环引用的问题。
可达性分析算法
GCRoots:
1.虚拟机栈中引用的对象。
2.本地方法栈中JNI引用的对象。
3.方法区中常量引用的对象。
4.方法区中类静态属性实体引用的对象。
具体实现:
这是Java所使用的判断对象是否存活的算法,从GCRoot开始搜索,搜索走过的路径称为引用链,当对象不在任何引用链中时,说明对象废弃。
垃圾收集机制
新生代
针对新生代的垃圾收集称为MinorGC,MinorGC常用复制算法,需要STW。
触发时间:
1.Eden区空间不足时。
具体实现:
将Eden区和Survivor From区中的有效对象打上标记,然后复制到Survivor To区中,释放Eden区和Survivor From区的所有空间,随后From和To会交换名字,为下一次GC做准备。
当一个对象经历过一次GC后仍然存活,它的年龄会加1,当年龄大于等于6时,会被放入Old区;或者是Survivor To区空间不足时,当一个年龄值的对象超过Survivor区中对象数量的一半,那么大于该年龄的对象都会被转移至Old区。
老年代
针对老年代的垃圾收集称为MajorGC,MajorGC常用标记清除和标记整理算法。
触发时间:
1.调用System.gc()时,建议触发,但不一定触发。
2.Old区空间不足时。
3.方法区空间不足时。
4.通过MinorGC进入Old区的平均内存大于Old区可用内存时。
5.MinorGC时,进入Survivor To区的对象大于其可用内存时,会转存到Old区,此时如果Old区的可用内存也小于该对象,则触发。
具体实现:
标记清除由于在原地删除对象,会产生内存碎片,当大对象需要存放时,这些内存碎片不能得到有效利用,只能触发下一次MajorGC,因此有了对此优化的标记整理法,标记整理法在删除对象的同时,会重新整理对象的内存空间,来最大程度的提高Old区的利用率,缺点是处理时间较慢,且需要STW。
小结
相较而言,MinorGC的触发比MajorGC的触发更频繁,MinorGC常用的复制算法和MajorGC的标记整理算法都需要STW,而MinorGC的需要的时间更少。
常用垃圾收集器
MinorGC
Serial:串行,单线程,复制算法,STW
ParNew:并发,多线程,复制算法,STW
Parallel Scavenge:并行,多线程,复制算法,STW(更专注于吞吐量,而不是单次GC的时间,多用于客户端)
MajorGC
SerialOld:串行,单线程,标记整理算法,STW
CMS:并发,多线程,标记清理算法
ParallelOld:并发,多线程,标记整理算法,STW(和Parallel Scavenge搭配使用,专注于吞吐量)

浙公网安备 33010602011771号