首页 > 技术文章 > jvm分代算法以及参数调优

wanghy898 2019-07-08 17:26 原文

新生代和老年代(分代算法)

原理:根据垃圾回收机制的不同,Java堆有可能拥有不同的结构,最为常见的就是将整个Java堆分为新生代和老年代。其中新生代存放新生的对象或者年龄不大的对象,老年代则存放老年对象。新生代分为eden区、s0区、s1区,s0和s1也被称为from和to区域,他们是两块大小相等并且可以互换角色的空间。绝大多数情况下,对象首先分配在eden区,在新生代回收后,如果对象还存活,则进入s0或s1区,之后每经过一次新生代回收,如果对象存活则它的年龄就加1,对象达到一定的年龄后,则进入老年代。

新生代:刚new出来不久的对象,不经常使用 会被优先回收  为堆内存的1/3或者1/4,采用复制算法实现
老年代:经常被使用的对象。使用15次后就会放入老年代中 比新生代优先级低 不会优先回收 如果老年代也不经常使用也会被回收,采用标记压缩算法(也叫标记整理算法)

复制算法

即把内存分成相等的AB两块,每次只使用其中的一块。比如当A内存使用完后,就把A中还存活着的对象复制到另外一块内存中去(B),然后再把已经使用过的内存清理掉。优点:这样就不用考虑内存碎片的问题了。缺点:内存减半,代价略高。

标记压缩算法(标记-整理)

复制算法当存活的实例多的时候,就需要大量复制,效率不高,不适合老年代。那么就可以采用标记-整理算法。也就是先标记,然后对存活的对象进行移动,全部移动到一端,然后再对其它的内存进行清理。

2.设置新生代与老年代优化参数

设置新生代比例参数
参数: -Xms20m -Xmx20m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC -XX:NewRatio=2

堆的参数配置
-XX:+PrintGC 每次触发GC的时候打印相关日志
-XX:+UseSerialGC 串行回收
-XX:+PrintGCDetails 更详细的GC日志
-Xms 堆初始值
-Xmx 堆最大可用值
-Xmn 新生代堆最大可用值
-XX:SurvivorRatio 用来设置新生代中eden空间和from/to空间的比例.
含义:-XX:SurvivorRatio=eden/from=den/to
-XX:SurvivorRatio 用来设置新生代中eden空间和from/to空间的比例.

总结:在实际工作中,我们可以直接将初始的堆大小与最大堆大小相等,
这样的好处是可以减少程序运行时垃圾回收次数,从而提高效率。

3.调优

尽量减少垃圾回收的次数,多了的话会影响效率
堆的初始值与堆内存的最大值要保持一致
初始值越小,垃圾回收次数越多(生产环境上面初始值和最大值一定要一致)
针对JVM堆的设置,一般可以通过-Xms -Xmx限定其最小、最大值,
(1)为了防止垃圾收集器在最小、最大之间收缩堆而产生额外的时间,我们通常把最大、最小设置为相同的值
(2)年轻代和年老代将根据默认的比例(1:2)分配堆内存,可以通过调整二者之间的比率NewRadio来调整二者之间的大小,
也可以针对回收代,比如年轻代,通过 -XX:newSize -XX:MaxNewSize来设置其绝对大小。
同样,为了防止年轻代的堆收缩,我们通常会把-XX:newSize -XX:MaxNewSize设置为同样大小

GC

GC(或Minor GC):收集生命周期短的区域(Young area)。

Full GC (或Major GC):收集生命周期短的区域(Young area)和生命周期比较长的区域(Old area)对整个堆进行垃圾收集。

他们的收集算法不同,所以使用的时间也不同。

Minor GC后,Eden是空的吗?

是的,Minor GC会把Eden中的所有存活对象都移到Survivor区域中,如果Survivor区中放不下,那么剩下的存活对象就被移到Old generation 中。

GC 效率也会比较高,我们要尽量减少 Full GC 的次数。 当显示调用System.gc() 时,gc does a full collection(both young generation and tenured generation).

显式调用system.gc()会触发full gc,对象在Eden出生每经历一次MInor GC后仍然存活,并且能被Survivor容纳,就会被移动到Survivor,

并设定年龄为1.以后在Survivor每"熬过"一次Minor GC,年龄就增加一岁,当年龄超过一定值(15次)就被移动到老年代,MaxTenuringThreshold用于设置年龄阈值,但是如果Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,

年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。

大对象直接进入老年代,比如长数组或长字符串,-XX:PretenureSizeThreshold用于设置大于这个值直接在老年代分配。

 

推荐阅读