第一讲:JVM垃圾回收机制

248 阅读5分钟

前言之案例

一、fastjson引发的老年代增长;

二、连接池配置有误导致连接不断往老年代挪动;

三、调用外部接口同步数据,服务方接口扩展字段大量增加值导致调用方oom;

四、StringBuffer.append没控制长度导致内存溢出;

五、Local cache不断替换导致老年代持续增长;

六、metric统计信息导致内存溢出;


前言之案例

一、fastjson引发的老年代增长;

二、连接池配置有误导致连接不断往老年代挪动;

三、调用外部接口同步数据,服务方接口扩展字段大量增加值导致调用方oom;

四、StringBuffer.append没控制长度导致内存溢出;

五、Local cache不断替换导致老年代持续增长;

六、metric统计信息导致内存溢出;

垃圾回收算法分类


一、引用计数法(Reference Counting Collector):最古老的垃圾回收算法。
二、tracing算法(Tracing Collector)

java中可作为GC Root的对象有
1.虚拟机栈中引用的对象(本地变量表)
2.方法区中静态属性引用的对象
3. 方法区中常量引用的对象
4.本地方法栈中引用的对象(Native对象)

1、标记-清除(Mark—Sweep)

被誉为现代垃圾回收算法的思想基础。
标记-清除算法采用从根集合进行扫描,对存活的对象对象标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收,如上图所示。标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记-清除算法直接回收不存活的对象,因此会造成内存碎片。


2、复制算法(Copying)

该算法的提出是为了克服句柄的开销和解决堆碎片的垃圾回收。建立在存活对象少,垃圾对象多的前提下。
它开始时把堆分成 一个对象 面和多个空闲面, 程序从对象面为对象分配空间,当对象满了,基于copying算法的垃圾 收集就从根集中扫描活动对象,并将每个 活动对象复制到空闲面(使得活动对象所占的内存之间没有空闲洞),这样空闲面变成了对象面,原来的对象面变成了空闲面,程序会在新的对象面中分配内存。一种典型的基于coping算法的垃圾回收是stop-and-copy算法,它将堆分成对象面和空闲区域面,在对象面与空闲区域面的切换过程中,程序暂停执行。
此算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去后还能进行相应的内存整理,不会出现碎片问题。但缺点也是很明显,就是需要两倍内存空间。


3、标记-整理(或标记-压缩算法,Mark-Compact,又或者叫标记清除压缩MarkSweepCompact)

此算法是结合了“标记-清除”和“复制算法”两个算法的优点。避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。标记-整理算法采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的指针。标记-整理算法是在标记-清除算法的基础上,又进行了对象的移动,因此成本更高,但是却解决了内存碎片的问题。在基于Compacting算法的收集器的实现中,一般增加句柄和句柄表。

分代回收策略


(Generational Collecting)
基于这样的事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率。


新生代由于其对象存活时间短,且需要经常gc,因此采用效率较高的复制算法,其将内存区分为一个eden区和两个suvivor区,默认eden区和survivor区的比例是8:1,分配内存时先分配eden区,当eden区满时,使用复制算法进行gc,将存活对象复制到一个survivor区,当一个survivor区满时,将其存活对象复制到另一个区中,当对象存活时间大于某一阈值时,将其放入老年代。

老年代和永久代因为其存活对象时间长,因此使用标记清除或标记整理算法

新生代:复制算法(新生代回收的频率很高,每次回收的耗时很短,为了支持高频率的新生代回收,虚拟机可能使用一种叫做卡表(Card Table)的数据结构,卡表为一个比特位集合,每个比特位可以用来表示老年代的某一区域中的所有对象是否持有新生代对象的引用。这样在新生代GC时,可以不用花大量时间扫描所有老年代对象,来确定每一个对象的引用关系,而可以先扫描卡表,卡表的标记为为1时,才需要扫描给定区域的老年代对象)

老年代:标记清除算法,标记压缩算法(回收频率比较低,耗时更多)



垃圾回收器

垃圾回收器的任务是识别和回收垃圾对象进行内存清理。
新生代收集器使用的收集器:Serial、ParNew、Parallel Scavenge;老年代收集器使用的收集器:Serial Old(MSC)、Parallel Old、CMS


总结:
1、Serial old和新生代的所有回收器都能搭配;也可以作为CMS回收器的备用回收器;
2、CMS只能和新生代的Serial和ParNew搭配,而且ParNew是CMS默认的新生代回收器;
并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态
并发(Concurrent):指用户线程和垃圾收集线程同时执行(但不一定是并行的,可能是交替执行),用户程序继续运行,而垃圾收集程序运行在另外的CPU上。