目录
1. 概述
环境:JDK1.6
JAVA堆内存分为新生代(Young)和老年代(Old),比例为1:2。也就是如果有1.5G的堆内存,新生代内存为512M,老年代为1G。
而新生代又分为三块区域,Edent
和Survivor 1
和 Survivor 2
。
Edent
和Survivor 1
和 Survivor 2
比例分别是 8:1:1。也就是 512MB的 Young
区域, Survivor 1
和 Survivor 2
各51.2MB, Edent
409.6MB
2. 堆内存运行流程:
1、用户创建的对象首次放入到Eden
区域,Eden
区域满了之后,JVM就会运行Minor GC
,把Eden
和Survivor 1
区域的废弃对象从内存中删除,把继续使用的内存移动到Survivor 2
中,并把移动到该区域的所有对象年龄加1。
2、Survivor 1
和Survivor 2
共同维护对象,Survivor 2
会把上次Minor GC
放在Survivor 2
中得对象移动到Survivor 1
中。
3、如此反复运行,当对象的年龄到达15时,会把Survivor 2
中得对象移动到Old区域
。
4、所谓的Major GC
是发生在Old 区域
满了之后发生的。
3. Warning
3.1. Warning1:不到15岁就直接进入老年代
多少岁进入老年代的JVM参数: -XX:MaxTenuringThreshold
默认值15.
当发生Minor GC
时,如果 Eden
对象有 60MB,Survivor 2
只有 51.2MB,放不下那么就会直接把对象放到Old
区域,这就导致了严重性问题,这中间的对象可能并非永久性的,那么很容易使Old
区域发生Major GC
。而Major GC
会使所有线程暂停。所以调优部分基本上都是这里。
3.2. Warning2:动态对象年龄判断
1、 Survivor 2
的内存超过50%,即25.6M;
2、 Survivor 2
的对象 ≥ 2岁时;
以上两个条件满足时,这两岁以上的对象也会直接进入 Old
区域;
3.3. Warning3:大对象直接进入老年代
-XX:PretenureSizeThreshold
默认是 1048576,单位字节,即 1MB。
这个参数是对象超过这个大小,直接进入老年代,比如大Map等。
参数目的,一个大对象来回在 Eden
和 Survivor
区域中复制,非常浪费时间;一般大对象在业务系统中也不是个临时对象;
4. JVM垃圾回收算法
4.1. 新生代
垃圾回收算法为复制算法,保证 Minor GC
之后的内存碎片,复制到另一个 Survivor 为空的内存区域中,这样保证了内存对象总是有序的,没有内存碎片;
回收器: ParNew
4.2. 老年代
垃圾回收算法为标记整理算法,与标记清除算法不同的是,标记清除会产生非常多的内存碎片,而标记整理只会产生少量的内存碎片,但是会消耗更多GC时间。
回收器: CMS
5. Minor GC 的触发时间
Minor GC触发条件:当Eden区满时,触发Minor GC。
6. Full GC 的触发时间
(1)老年代空间不足(-XX:CMSInitiatingOccupancyFaction,默认92%)
(2)通过Minor GC后进入老年代的平均大小大于老年代的可用内存
(3)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小。
(4)没有打开“-XX:HandlePromotionFailure”选项,结果老年代可用内存最多也就1G,新生代对象总大小最多可以有1.8G
原创文章,转载请注明: 转载自LoserZhao – 诗和远方[ http://www.loserzhao.com/ ]
文章的脚注信息由WordPress的wp-posturl插件自动生成
0 条评论。