JVM系列之三:常用JVM配置参数

GC参数

串行收集器

– 最古老,最稳定

– 效率高

– 可能会产生较长的停顿

– 新生代、老年代使用串行回收

– 新生代复制算法

– 老年代标记-压缩

– -XX:+UseSerialGC

 

并行收集器

– 新生代复制算法,老年代标记-压缩

– -XX:+UseParNewGC

– Serial收集器新生代的并行版本

– 只会影响新生代

– 可以和CMS算法一起使用

– -XX:+UseParallelGC

– ParNew是这个的升级版

– 使用Parallel收集器老年代串行

– 更加关注吞吐量

– -XX:+UseParallelOldGC

– 使用Parallel收集器并行老年代

– -XX:MaxGCPauseMills

– 最大停顿时间,单位毫秒

– GC尽力保证回收时间不超过设定值

– -XX:GCTimeRatio

– 0-100的取值范围

– 垃圾收集时间占总时间的比

– 默认99,即最大允许1%时间做GC

– -XX:MaxGCPauseMills冲突,因为停顿时间和吞吐量不可能同时调优

– 多线程,需要多核支持

– -XX:ParallelGCThreads 限制线程数量

– 建议根据PCCPU核数来限制线程数量

 

 

CMS收集器

– Concurrent Mark Sweep 并发标记清除

– 标记-清除算法

– 并发阶段会降低吞吐量

– 老年代收集器(新生代使用ParNew

– -XX:+UseConcMarkSweepGC

– -XX:+ UseCMSCompactAtFullCollection

– Full GC后,进行一次碎片整理

– 整理过程是独占的,会引起停顿时间变长

– -XX:ParallelCMSThreads

– 设定CMS的线程数量

– -XX:CMSFullGCsBeforeCompaction

– 设置进行几次Full GC后,进行一次碎片整理

– -XX:+CMSClassUnloadingEnabled

– 允许对类元数据进行回收

– -XX:CMSInitiatingPermOccupancyFraction

– 当永久区占用率达到这一百分比时,启动CMS回收

– -XX:+UseCMSInitiatingOccupancyOnly

– 表示只在到达阀值的时候,才进行CMS回收

– 特点

– 尽可能降低停顿

– 会影响系统整体吞吐量和性能

– 比如,在用户线程运行过程中,分一半CPU去做GC,系统性能在GC阶段,反应速度就下降一半

– 清理不彻底

– 因为在清理阶段,用户线程还在运行,会产生新的垃圾,无法清理

– 因为和用户线程一起运行,不能在空间快满时再清理

– -XX:CMSInitiatingOccupancyFraction设置触发GC的阈值

– 如果不幸内存预留空间不够,就会引起concurrent mode failure

33.348: [Full GC 33.348: [CMS33.357: [CMS-concurrent-sweep: 0.035/0.036 secs] [Times: user=0.11 sys=0.03, real=0.03 secs]

(concurrent mode failure): 47066K->39901K(49152K), 0.3896802 secs] 60771K->39901K(63936K), [CMS Perm : 22529K->22529K(32768K)], 0.3897989 secs] [Times: user=0.39 sys=0.00, real=0.39 secs]

使用串行收集器作为后备

– CMS运行过程

– 初始标记

– 根可以直接关联到的对象

– 速度快

– 并发标记(和用户线程一起)

– 主要标记过程,标记全部对象

– 重新标记

– 由于并发标记时,用户线程依然运行,因此在正式清理前,再做修正

– 并发清除(和用户线程一起)

– 基于标记结果,直接清理对象

 

 

Trace跟踪参数

-XX:+PrintGC

– 可以打印GC的简要信息

– 示例

 [GC 4790K->374K(15872K), 0.0001606 secs]

[GC 4790K->374K(15872K), 0.0001474 secs]

-verbose:gc

功能和-XX:+printGC一样,但是这个是稳定版,-XX:+PrintGC是非稳定版本,可能在未通知的情况下删除。

-XX:+PrintGCDetails

– 打印GC详细信息

– 示例

[GC[DefNew: 4416K->0K(4928K), 0.0001897 secs] 4790K->374K(15872K), 0.0002232 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

系统运行完成前的快照:堆信息

 

-XX:+PrintGCTimeStamps

– 打印CG发生的时间戳

– 单独使用无效,一般和-XX:+PrintGC、-XX:+PrintGCDetails等参数搭配使用

-Xloggc:log/gc.log

– 指定GC log的位置,以文件输出

– 帮助开发人员分析问题

-XX:+PrintHeapAtGC

– 每次一次GC后,都打印堆信息

-XX:+TraceClassLoading

– 监控类的加载

[Loaded java.lang.Object from shared objects file]

[Loaded java.io.Serializable from shared objects file]

[Loaded java.lang.Comparable from shared objects file]

[Loaded java.lang.CharSequence from shared objects file]

[Loaded java.lang.String from shared objects file]

[Loaded java.lang.reflect.GenericDeclaration from shared objects file]

[Loaded java.lang.reflect.Type from shared objects file]

-XX:+PrintClassHistogram

– 按下Ctrl+Break后,打印类的信息

– 分别显示:序号、实例数量、总大小、类型

– 示例

num     #instances         #bytes  class name

----------------------------------------------

    1:        890617      470266000  [B

   2:        890643       21375432  java.util.HashMap$Node

   3:        890608       14249728  java.lang.Long

   4:            13        8389712  [Ljava.util.HashMap$Node;

   5:          2062         371680  [C

   6:           463          41904  java.lang.Class

 

堆的分配参数

-Xmx -Xms

– 指定最大堆和最小堆

– Java会尽可能维持在最小堆

– 当堆使用的内存超过了最小值并且小于最大值,JVM会自动扩展堆内存,但不会扩展超过最大值。

-Xmn

– 设置新生代大小,老年代大小则默认为堆内存减去新生代的大小

-XX:NewRatio=4

– -Xmn会有冲突,以-Xmn为准

– 新生代(eden+2*s)和老年代(不包含永久区)的比值

– 4 表示 新生代:老年代=1:4,即年轻代占堆的1/5

– 默认值为2

-XX:SurvivorRatio=8

– 设置两个Survivor区和eden的比

– 8表示 两个Survivor :eden=2:8,即一个Survivor占年轻代的1/10

– 默认值为8

-XX:+HeapDumpOnOutOfMemoryError

– OOM时导出堆到文件

-XX:HeapDumpPath=d:/a.dump

– 导出OOM的路径

-XX:OnOutOfMemoryError

– OOM时,执行一个脚本

-XX:OnOutOfMemoryError=D:/tools/jdk1.7_40/bin/printstack.bat %p

示例

示例1

 

堆的最大最小都设为20m,新生代大小为1m

程序创建10个大小为10M的对象

运行结果:没有触发GC,因为新生代空间太小,对象直接分配在老年代空间

示例2

 

堆的最大最小都设为20m,新生代大小为15m

程序创建10个大小为10M的对象

运行结果:没有触发GC,对象全部分配在eden空间

示例3

 

堆的最大最小都设为20m,新生代大小为7m

程序创建10个大小为10M的对象

运行结果:进行了2次新生代GC,一共回收7M 剩余3M,S0 s1 太小无法周转,GC之后对象保存在老年代

示例4

 

堆的最大最小都设为20m,新生代大小为7meden区和幸存区(from+to)各占新生代的一半大小

程序创建10个大小为10M的对象

运行结果:一共回收7M 剩余3M,老年代没有使用

总结

– 根据实际事情调整新生代和幸存代的大小

– 官方推荐新生代占堆的3/8

– 幸存代占新生代的1/10

– OOM时,记得Dump出堆,确保可以排查现场问题

永久区分配参数

-XX:PermSize  -XX:MaxPermSize

– 设置永久区的初始空间和最大空间

– 他们表示,一个系统可以容纳多少个类型

– 如果堆空间没有用完也抛出了OOM,有可能是永久区导致的

– 默认值64m64VM会扩大30%

 

栈的分配参数

-Xss

– 通常只有几百K

– 决定了函数调用的深度

– 每个线程都有独立的栈空间

– 局部变量、参数 分配在栈上

– 计算可创建线程数

(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads

MaxProcessMemory 指的是一个进程的最大内存
JVMMemory         JVM内存
ReservedOsMemory  保留的操作系统内存
ThreadStackSize      线程栈的大

– 默认值

· Linux/ARM (32-bit): 320 KB

· Linux/i386 (32-bit): 320 KB

· Linux/x64 (64-bit): 1024 KB

· OS X (64-bit): 1024 KB

· Oracle Solaris/i386 (32-bit): 320 KB

· Oracle Solaris/x64 (64-bit): 1024 KB

 

总结

性能的根本在应用,GC参数属于微调,设置不合理,会影响性能,产生大的延时

升级JDK可能会带来额外的性能提升!

猜你喜欢

转载自blog.csdn.net/qq_21508727/article/details/80622397