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搭配使用,专注于吞吐量)

posted @ 2020-09-03 15:27  昆梧  阅读(262)  评论(0)    收藏  举报