浅谈Java8中的GC

之前谈了JVM,这次说一个Java中的重点:GC。

GC是Java的一个重要特性,它会自动回收内存中的垃圾,而不用像C/C++一样,需要手动回收垃圾。
了解过JVM我们就知道,根据各个区的特性,方法区触发GC较少,GC主要是对堆内存的对象进行回收。

堆内存结构

Java8中堆内存分为新生代和老年代,其中新生代占堆内存的1/3,老年代占堆内存的2/3。
见名思意,刚创建的对象存在于新生代中,当他们存活过一定的时间后,就会被移动到老年代。

而在新生代中,为了方便垃圾回收,所以我们又将新生代划分为Eden,Survivor两个区域;而Survivor继续划分为from、to两个部分。
新创建的对象,首先是存放在Eden中,这些对象绝大多数都活不了多久,根据经验大约为8:1,所以JVM默认情况下Eden : Survivor from : Survivor to 为 8 : 1 : 1。

现在我们知道了堆内存是怎么划分的,但是为什么这么划分,我们还需要知道更多的东西。

GC算法

GC算法目的就是为了合理高效的回收垃圾。
目前GC算法主要有3种:

复制算法

将内存平均分成两部分,然后每次只使用其中的一部分,当这部分内存满的时候,将内存中所有存活的对象复制到另一个内存中,然后将之前的内存清空,只使用这部分内存,循环下去。
这个地方一看就明白了Survivor就是使用的复制算法,最开始所有的对象都在from区域中,然后将存活的对象复制到to区域,然后将from区域清空。之后to区域就变成了from区域,from区域就变成了to区域,再次执行以上操作。
它的优点就是实现简单,运行高效。缺点就是比较浪费空间。

标记-清除算法

算法分为2个阶段:1.标记需要回收的对象,2.回收被标记的对象。
这个算法效率较低,而且也有很大的缺点:内存碎片问题。内存中容易出现大量非连续内存空间,当开辟大空间时,如果找不到连续的内存空间,容易提前触发一次GC。所以现在一般都不使用这种方法。

标记-整理算法

1.标记存活的对象,2.将存活的对象向内存的一端移动,并直接清空另一端的内存空间。
这个算法解决了“标记-清除算法”的内存碎片问题,同时直接清空某一端的内存也比单个收回效率高。

GC算法适用总结

了解了GC算法后,我们就可以明白为什么堆内存要进行划分了。
首先,新创建的对象更容易被回收,所以效率是关键;已经存活很久的对象,一般较少被回收,所以我们划分了新生代和老年代。
最初,对象在Eden中被创建,当Eden空间满时,则需要进行一次GC,根据特点,使用复制算法会更加合理高效,所以我们将存活对象复制到Survivor from空间,并清空Eden。
之后,Survivor from空间满,则将from空间中存活的对象复制到to空间,并给对象的年龄+1,一直这样反复,直到对象的生命大于15,则复制到老年代中。
在老年代中,根据特点我们则使用标记-整理算法,虽然效率不及复制算法,但节约空间,而且不会产生内存碎片。

如何确定对象是否存活

了解GC算法后我们会有一个疑问,怎么知道对象是否应该被回收呢?
有2种方法:
1. 引用计数法。
当A对象引用B对象时,B的引用计数会+1。但是这种方法有一个缺陷,如果此时B对象又引用了A对象,那么会出现循环引用的情况,A和B就可能形成内存孤岛,导致不能被回收。
2. 可达性分析。
从根对象开始,如果能到达某个对象,则说明该对象还在被使用;如果不能到达某个对象,则说明该对象需要被回收。这种方法解决了循环引用的问题,也是目前GC使用的方法。

拓展一下,GC Root对象包括:
1. 虚拟机栈(栈帧中的本地变量表)中引用的对象
2. 方法区中类静态属性引用的对象
3. 方法区中常量引用的对象
4. 本地方法栈中JNI(即一般说的Native方法)引用的对象

G1 GC

目前Java8默认使用G1作为GC,因为G1适合于服务器的多核、大内存的情况。
G1做了很大的修改,这里只能简单提一提,比如取消了新生代、老年代的物理空间的划分,将内存分为一块快小部分等,这一特性使它可以合理利用多核性能,并发的进行垃圾回收。同时也可以设置GC的最大暂停时间,使Stop The World的时间变的可控。

JVM调优

对于新生代的GC我们称为Minor GC,对于老年代的GC我们称为Major GC,整个堆内存的GC我们称为Full GC。
JVM调优主要就是为了减少Full GC的发生。因为Full GC时会Stop The World,造成性能问题。
对此一般来说需要尽可能的加大内存,但是服务器的理论支持内存有上线,而且老板的预算也有限,所以就需要针对程序的情况,手动对内存划分的大小做修改。一般来说需要配合一些工具帮助我们做出判断。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据