JVM学习与调优

 

 

 

1 堆:存放数据

  栈:存放逻辑

2 虚拟机: 栈溢出,则栈大小设置-Xss  默认值为1M 但一般会不到200k,所以会将默认值调整小点 

  

Java虚拟机本身:-Xms,-Xmx,-Xss;

系统限制:

/proc/sys/kernel/pid_max,

/proc/sys/kernel/thread-max,

max_user_process(ulimit -u),

/proc/sys/vm/max_map_count。

 

3 堆内存溢出

强引用内存泄露:new 出来的对象是基本上是强引用,这种引用申请不到内存,则内存泄露 。

    强引用环境,垃圾回收时需要严格判断当前对象是否被强引用,如果被强引用则不会被回收。

软引用:当做缓存来用(内存受限的时候用,否则用强引用更好),当垃圾回收时候,如果内存紧张则软引用会被回收,否则不回收。

 

弱引用(与软引用类似):申请不到内存则会进行内存回收,不会有内存泄露 

 

4 垃圾回收算法:

  1 引用为0

  2 标记清楚,它会遍历整个堆来标记无用的对象,  ()

  3 复制回收 

  四个区: e,s0,s1 ,old ,每次回收后剩下的对象会向后面的区转移 ,前三个为新生代,old为老年代 

  4 标记整理:

 

5 出发回收:

  1) Scavenge: e区申请空间失败(即满了),则出发此回收

  2)full GC:比较慢,尽量减少这种GC使用,一下会产生这种GC

     年老带写满、持久带写满、System.gc、上一次GC后Heap各个区域分配策略动态变化

 

6 配置垃圾回收器  

串行垃圾回收器:数量比较小,100M左右,一般单处理器对响应时间无要求 : -XX:+UseSerialGC 

并行垃圾回收: 特点:,但吞吐量高。适合, 多核多处理器,响应时间无要求的中大型应用:-XX:+UseParallelOldGC , -XX:ParalleGCThreads 并行线程数量

  最大暂停时间:-XX:MaxGCPauseMills=N ,如后台处理,科学计算

  吞吐量:-XX:GCTimeRatio=N

并发处理器:“响应时间高要求”多cpu,对响应时间有较高要求的中大型应用,如web服务器,应用服务器,集成开发环境

     

7 常见配置汇总:

  堆设置:

  -Xms:初始堆大小 <4G 

  -Xmx:最大堆大小 <4G

  -XX:NewSize=n:设置年轻带大小

  -XX:NewRatio=n设置年轻带和年老带的比值。如为3,则年轻带与年老带比值为1:3

 年轻带占整个年轻带年老带和的1/4

   -XX:SurvivorRatio=n :年轻带中Eden区与两个Survivor区的比值。。

 注意Survivor区有两个。如:3表示Eden:Survivor=3:2一个Survivor区占整个年轻带的1/5

  -XX:MaxPermSize=n 设置持久代大小

  收集器设置:

   -XX:+UseSeralGC 设置串行收集器

   -XX:+UseParallelGC 设置并行收集器

   -XX:+UseParalledlOldGC 设置并行年老带收集器

   -XX:+UseConcMarkSweepGC:设置并发收集器 

   垃圾回收统计信息:打印垃圾回收信息,以便查看参数设置是否正确

   -XX:+PrintGC

   -XX:+PrintGCDetails

   -XX:+PrintGCTimeStamps

   -Xloggc:filename 

 

  测试堆栈设置:打印gc信息,并且打印出堆溢出的问题-Xms50m -Xmx50m -verbose:gc -Xrunhprof:heap=sites

  并行收集器设置:

    -XX:ParallelGCThreads=n :设置并行收集器收集时使用的CPU数,并行线程数。

    -XX:MaxGCPauseMillis=n: 设置并行收集最大暂停时间

    -XX:GCTimeRatio=n 设置垃圾回收时间占程序运行时间的百分比:公式1/1+n

 

  并发收集器设置:

  -XX:+CMSIncrementalMode  设置为增量模式 适用单CPU

  -XX:ParallelGCThreads=n  设置并发收集器年轻带收集方式为并行收集器,使用CPU

 数。并行收集器线程数

 

JVM中最大堆大小的三方面限制:相关操作系统数据模型限制(32还是64位);系统可用虚拟内存限制;

系统的可用物理内存限制。32位系统下,一般限制在1.5-2G。

64位操作系统内存无限制 。windows Server 2003系统,3.5G物理内存,

JDK5.0下测试最大设置为1478m

典型设置1:

java -Xmx3550m-Xms3550m-Xmn2g-Xss128k

-Xmx3550m: 设置JVM最大可用内存为3550M

-Xms3550m:设置JVM初始内存为3550M。这个值设置与-Xmx形同,以避免每次

垃圾回收后JVM重新分配内存。

-Xmn2g:设置年轻带大小为2G。整个堆大小=年轻代+年老代大小+持久代大小。

持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。

此值对系统性能影响较大,Sun官方推荐为整个堆大小3/8.

 -Xss128k:设置每个线程堆栈大小。以后每个线程堆栈大小为1M,以前每个线程

堆栈大小为256K。根据应用的线程所需内存大小进行调整。在相同物理内存下,

减小这个值能生成更多的线程。但操作系统对一个进程内的线程数还是有限制的,

不能无限制生成,经验值为3000-5000左右。

典型设置2:

 java-Xmx3550m-Xms3550m-Xss128k-XX:NewRatio=4-XX:SurvivorRatio=4

 -XX:MaxPermSize=16m-XX:MaxTenuringThreShold=0

 -XX:newRatio=4 :设置年轻带(包括Eden和两个S区)与年老带的比值(除去持久代)

设置为4,则年轻带与年老代所占比值为1:4,年轻带占整个堆栈的1/5.

 -XX:SurvivorRatio=4 :设置年轻代中Eden与Survivor区的大小比值。设置为4,则两个Survivor区

与一个Eden区的比值为2:4,一个Survivor区占整个年轻带的1/6

-XX:MaxPermSize=16m :设置持久代大小为16m

-XX:

MaxTenuringThreshold=0 设置垃圾最大年龄。如果设置为0,则年轻带对象不经Survivor区,直接

进入年老代。对于年老代比较多的应用可以提高效率,如果将此值设置为一个较大的值,则

年轻代对象会在S区进行多次复制,则会增加对象年轻代存活时间.

8 回收器选择:

JVM给了三种回收器:串行收集器,并行收集器,并发收集器

默认JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在启动时候加入相应参数。

jdk5.0以后JVM会根据当前系统配置

 

吞吐量优先的并行收集器:

并行收集器主要是以达到一定吞吐量为目标,适用科学技术和后台处理器:

典型配置:

 

java-Xmx3800m-Xms3800m-Xmn2g-Xss128k-XX:+UseParallelGC

-XX:ParallelGCThreads=20

-XX:+UseParalelGC:选择垃圾收集器为并行收集器。此配置对年轻代有效。

即上述配置下,年轻代适用并发收集,而年老带仍旧适用串行收集。

-XX:ParallelGCThreads=20: 配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。

此值最好配置与处理器数目相等。

 

java-Xmx3550m-Xms3550m-Xmn2g-Xss128k-XX:+UseParallelGC

-XX:ParallelGCThreads=20-XX:+UseParallelOldGC

-XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0

支持对年老代并行收集。

 

java-Xmx3550m-Xms3550m-Xmn2g-Xss128k-XX:+UseParallelGC

-XX:MaxGCPauseMillis=100

-XX:MaxGCPauseMillis=100 设置年轻代垃圾回收的最长时间,如果

无法满足此时间,JVM会自动调整年轻代大小,以满足此值。

 

java-Xmx3550m-Xms3550m-Xmn2g-Xss128k-XX:+UseParallelGC

-XX:MaxGCPauseMillis=100-XX:+UseAdaptiveSizePolicy

-XX:+UseAdaptiveSizePolicy 设置此选项,并行收集器会自动选择年轻代区大小

和相应的Survivor区的比例,以达到目标系统规定的最低响应时间或者

收集频率,建议使用并行收集器时,一直打开。

 

    响应时间优先并发收集器:主要保证系统响应时间,减小垃圾手机时的

停顿时间,适用于应用服务器,电信领域等。

 

java-Xmx3550m-Xms3550m-Xmn2g-Xss128k-XX:+UseParallelGCThreads=20

-XX:+UseConcMarkSweepGC-XX:+UseParNewGC

-XX:+UseConcMarkSweepGC设置年老代并发收集,测试中配置这个后,

-XX:NewRatio=4的配置失效了。所以此时配置年轻带最好用-Xmn设置。

-XX:+UseParNewGC 设置年轻带为并行收集。可以与CMS收集同时使用。

   JDK5.0以后自动设置,所以无需设置。

 

java-Xmx3550m-Xms3550m-Xmn2g-Xss128k-XX:UseConcMakSweepGC

-XX:CMSFullGCsBeforeCompaction=5-XX:UseCMSCoimpactAtFullCollection 

-XX:UseCMSCoimpactAtFullCollection  :由于并发收集器不对内存空间进行空间压缩、整理,所以运行

一段时间后会产生碎片,使得运行效率降低。此值运行多少次GC后对

内存空间进行压缩,整理。

-XX:UseCMSCoimpactAtFullCollection :打开对年老带的压缩。可能会影响性能,但会产生碎片

 

总结:

年轻代大小选择

 

响应时间优先的应用:尽可能设置大,直到接近系统的最低响应时间限制 

在此种情况下,年轻代收集发生的频率也是最小的。同时,较少到达年老代对象。

 

吞吐量优先应用:尽可能的设置大,可能达到Gbit的程度,对响应时间没有要求

垃圾收集器可以并行进行,一般适合8CPU以上的应用。

 

 

年老代大小选择:

响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等

参数。如设置小了,可能会造成碎片,高回收频率以及应用暂停而使用传统的标记清楚方式;如果堆大了,则需要较长的

收集时间,最优方案需要参考下面数值:

 1)并发垃圾收集信息 2)持久代并发收集次数 3)传统GC信息 4)花在年轻代和年老代回收上的时间比例减少年轻代和

 年老代花费时间,一般会提高应用效率。

 

 

吞吐量优先的应用

一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代,因为这可以尽可能

回收掉大部分短期对象,减少中期对象,而年老代尽量存放长期存活对象。

 

较小堆引起碎片:

-XX:UseCMSCoimpactAtFullCollection  并发收集器,开启年老代压缩 

-XX:CMSFullGCsBeforeCompaction=0  : 设置多少次Full GC后对年老代压缩

 

 

9 调优方法与工具

 

JVM调优工具: Jconsole ,jProfile ,VisualVM 

 

Jconsole:jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用,对垃圾回收算法

有很详细的跟踪

JProfiler: 商业软件,付费功能强大

VisualVM :JDK自带,功能强大,与JProfiler类似推荐使用。

 

10 内存泄露检查

 

内存泄露一般是资源使用完毕后无法回收,从而导致新资源请求分配无法回收。

 

当访问没量不大,但是对使用一直在增长,一般是内存泄露了

解决:GMap打印无法回收的对象。

 

 

堆栈溢出:StackOverflowError ,一般递归或者循环造成 

线程堆栈满:Stack size too small 

 

JVM内存优化:  http://blog.csdn.net/ppby2002/article/details/6096837

 
 -server -Xmx2g -Xms2g -Xmn512m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true

 

 

 

 

 

 

 

猜你喜欢

转载自username2.iteye.com/blog/2278235