分代收集(Generational Collecting)
基于对对象生命周期分析后得出的垃圾回收算法,把对象分为年轻代、年老代、持久代,对不同生命周期的对象使用不同的算法进行回收。现在的垃圾回收器(从J2SE1.2开始)都是使用此算法。
Sun JVM内存区域分布图
1)Young(年轻代)
Young被划分为三个区间,Eden区和两个大小严格相同的Survivor区,其中Survivor区,在某一时刻只有其中一个是被使用的,另外一个留做垃圾收集时复制对象用。在Young区间变满的时候,Minor GC就会将存活的对象移到空闲的Survivor区中,根据JVM的策略,在经过几次Minor GC后,任然存活于Survivor区的对象将被移动到Tenured中。
2)Tenured(年老代)
Tenured主要保存生命周期长的对象,一般是一些老的对象,当一些对象在Young复制转移一定的次数以后,对象就会被转移到Tenured。一般如果系统中用了application级别的缓存,缓存中的对象往往会被转移到这一区间。
3)Perm(持久代)
Perm主要保存class、method、filed等对象,这部分的空间一般不会溢出,除非一次性加载了很多的类,不过在涉及到应用服务器的热部署时,有时候会遇到java.lang.OutOfMemoryError: PermGen space 的错误,造成这个错误的很大原因就有可能是每次热部署后,旧的class没有被卸载掉,这样就造成了大量的class对象保存在了Perm中,这种情况下一般重新启动应用服务器可以解决问题,或者通过-XX:MaxPermSize=<N> 将持久代大小设大点。
GC类型
大略上分以下2种
1)Minor GC
一般情况下,当新对象生成,并且在Eden申请空间失败时,就好触发Minor GC在Eden区清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后再整理Survivor的两个区。
2)Full GC
对整个堆进行整理,包括Young、Tenured以及Perm。Full GC比Minor GC要慢,因此应该尽可能减少Full GC。以下几种原因可能导致Full GC:
- Tenured或Perm被写满
- System.gc被显示调用
- 上一次GC后堆空间分配策略动态调整
JVM调优参数
JVM提供了相应的参数来对内存大小、垃圾回收算法进行配置。
Non-standard Java HotSpot VM Options
我在32位Windows Server 2003系统8GB物理内存,JDK1.6下测试,最大可设置为1536M,再多JVM就跑不起来了。
-Xms1536M 设置JVM启动后堆的初始内存(这里配置的JVM堆空间只是Young与Tenured)
-Xmx1536M 设置JVM启动后堆的最大内存,一般在生产环境中把这两个参数设为相同值,避免在“上一次GC后堆空间分配策略动态调整”而引起Full GC
-Xss1M 设置每个线程的Java栈大小
-XX:NewRatio=2 设置Tenured和Young的比值为2:1,这样Eden+2*Survivor=1/3
堆内存
-XX:SurvivorRatio=8 设置Eden和一个Survivor的比值为8:1,这样一个Survivor就占Young区的1/10.
-XX:PermSize=64M 设置持久代初始内存
-XX:MaxPermSize=128M 设置持久代最大内存
详细配置选项见:http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp#PerformanceTuning
垃圾收集器
JVM给了三种选择:串行收集器、并行收集器、并发收集器。串行收集器对于处理大数据量的情况时性能太低,所以一般选择使用并行收集器和并发收集器。J2SE5.0以后JVM会根据当前系统配置进行判断(机器配置只要有2个CPU和至少2GB的物理内存JVM将自动以-server模式运行)
1)吞吐量优先的并行收集器,通过 -XX:+UseParallelGC 指定
2)响应时间优先的并发收集器,主要是保证系统的响应时间,减少垃圾收集时的停顿时间。通过 -XX:+UseConcMarkSweepGC 指定。由于CMS GC是和应用并发执行的,因此需要耗费更多的CPU资源。
详细配置选项见:http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp#BehavioralOptions
Sun JDK自带的图形监控和管理工具jconsole
通过Sun JDK自带的一个图形监控和管理工具jconsole能很容易的看到当前虚拟机中的内存状态,我使用的JDK版本是jdk1.6.0_18,这个工具从jdk1.5就有了