JVM调优参数详解

JVM调优建议:

  1. 打印GC日志(GC日志的讲解,可以参考我的xmind给出的笔记,这里就不做过多说明了)
  2. 分析GC日志得出与性能相关的问题
  3. 调优JVM参数提升性能

此过程在实际生产中是反复调试的过程,通过不断地调整实现最优化,有时候不是一步到位的,打印GC日志:

-XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps 
-Xloggc:d:/jvm/jvmgc.log 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=d:/jvm/heapdump.hprof 
-XX:+DisableExplicitGC

其中 -XX:+DisableExplicitGC 禁止在代码中使用System.gc();

GC调优指南

源自官网:

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/ergonomics.html

首先给调优定下目标

  • 最大暂停时间目标
  • 吞吐量目标
  • 微调直达上述目标达到

maximum pause time goal -XX:MaxGCPauseMillis=n:每次GC时程序暂停最多多少毫秒;

throughput goal -XX:GCTimeRatio=n: 表示花费总时间百分之多少的CPU时间去运行程序;

footprint goal:如果其他目标都达到了,那么首先减少heap size,直到前两个goal不再满足,然后再慢慢增加,直到满足前面两个goal;

调优前的初始参数:

-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:d:/logs/gc.log
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=d:/logs/heapdump.hprof

吞吐量 最小停顿时间 最大停顿时间 平均停顿时间 Young GC  Full GC

(在调优GC的时候,可以按照如上表格字段借住工具进行每一次的记录)

G1调优建议

1、年轻代不要使用 -Xmn,-XX:NewRatio 显式设置大小,会覆盖暂停时间的目标;

2、暂停时间不要太严格,吞吐量目标是90%及以上;

GC常用参数

  • 堆、栈、元空间设置
  • -Xss:每个线程的栈大小
  • -Xms:初始堆大小,默认物理内存的1/64
  • -Xmx:最大堆大小,默认物理内存的1/4
  • -Xmn:新生代大小-XX:NewSize:设置新生代初始大小
  • -XX:NewRatio:默认2表示新生代占年老代的1/2,占整个堆内存的1/3。
  • -XX:YoungGenerationSizeIncrement=30 年轻代动态扩容增量
  • -XX:SurvivorRatio:默认8表示一个survivor区占用1/8的Eden内存,即1/10的新生代内存。
  • -XX:MetaspaceSize:设置元空间大小
  • -XX:MaxMetaspaceSize:设置元空间最大允许大小,默认不受限制,JVM Metaspace会进行动态扩展。

垃圾回收日志信息打印

-XX:+PrintGC 
-XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps 
-Xloggc:fifilename 

垃圾收集器设置

-XX:+UseSerialGC:设置串行收集器 
-XX:+UseParallelGC:设置并行收集器 
-XX:+UseParallelOldGC:老年代使用并行回收收集器 
-XX:+UseParNewGC:在新生代使用并行收集器 
-XX:+UseParalledlOldGC:设置并行老年代收集器 
-XX:+UseConcMarkSweepGC:设置CMS并发收集器 
-XX:+UseG1GC:设置G1收集器 
-XX:ParallelGCThreads:设置用于垃圾回收的线程数 

并行收集器设置

-XX:ParallelGCThreads:设置并行收集器收集时使用的CPU数。并行收集线程数;
-XX:MaxGCPauseMillis:设置并行收集最大暂停时间 
-XX:GCTimeRatio:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n) 

CMS收集器设置

-XX:+UseConcMarkSweepGC:设置CMS并发收集器 
-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。 
-XX:ParallelGCThreads:设置并发收集器新生代收集方式为并行收集时,使用的CPU数。并行收集线程数。 
-XX:CMSFullGCsBeforeCompaction: 设定进行多少次CMS垃圾回收后,进行一次内存压缩 
-XX:+CMSClassUnloadingEnabled: 允许对类元数据进行回收 
-XX:UseCMSInitiatingOccupancyOnly: 表示只在到达阀值的时候,才进行CMS回收;
-XX:+CMSIncrementalMode: 设置为增量模式。适用于单CPU情况 
-XX:ParallelCMSThreads: 设定CMS的线程数量 
-XX:CMSInitiatingOccupancyFraction: 设置CMS收集器在老年代空间被使用多少后触发 
-XX:+UseCMSCompactAtFullCollection:设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片的整理 

G1收集器设置

  • -XX:+UseG1GC:使用G1收集器
  • -XX:ParallelGCThreads:指定GC工作的线程数量
  • -XX:G1HeapRegionSize:指定分区大小(1MB~32MB,且必须是2的幂),默认将整堆划分为2048个分区
  • -XX:GCTimeRatio:吞吐量大小,0-100的整数(默认9),值为n则系统将花费不超过1/(1+n)的时间用于垃圾收集
  • -XX:MaxGCPauseMillis:目标暂停时间(默认200ms)
  • -XX:G1NewSizePercent:新生代内存初始空间(默认整堆5%)
  • -XX:G1MaxNewSizePercent:新生代内存最大空间
  • -XX:TargetSurvivorRatio:Survivor填充容量(默认50%)
  • -XX:MaxTenuringThreshold:最大任期阈值(默认15)
  • -XX:InitiatingHeapOccupancyPercen:老年代占用空间超过整堆比IHOP阈值(默认45%),超过则执行混合收集
  • -XX:G1HeapWastePercent:堆废物百分比(默认5%)
  • -XX:G1MixedGCCountTarget:参数混合周期的最大总次数(默认8)

常用JVM参数

-Xms
-Xmx
-XX:NewSize -XX:MaxNewSize 新生代大小 新生代最大大小
-XX:NewRatio 新生代与老年代的比例 -XX:SurvivorRatio eden区与s区的比例
-XX:MetaspaceSize -XX:MaxMetaspaceSize 元空间的大小 元空间的最大大小
-XX:+UseCompressedClassPointers 元空间是否使用类指针压缩,使用的话该区域默认占用1G大小
-XX:+UseCompressedOops ,OOP =“ordinary object pointer”普通对象指针,压缩对象指针,起到节约内存占用的效果,原理,解释器在解释字节码时,植入压缩指令(不影响正常和JVM优化后的指令顺序)。具体逻辑是,当对象被读取时,解压,存入heap时,压缩;
-XX:CompressedClassSpaceSize 设置元空间的类指针压缩区域的大小;
-XX:InitialCodeCacheSize 设置初始CodeCache大小
-XX:ReservedCodeCacheSize 用于设置code cache的最大大小,通常默认是240M
对象分配优先在Eden区分配
大对象直接进入老年代:-XX:PretenureSizeThreshold 用来指定超过这个大小的对象直接放入老年代;
长期存活的对象进入老年代:-XX:MaxTenuringThreshold -XX:+PrintTenuringDistribution -XX:TargetSurvivorRatio
-XX:MaxTenuringThreshold
设置的是年龄阈值,默认15
-XX:+PrintTenuringDistribution
打印一下对象的年龄信息
-XX:TargetSurvivorRatio
设定survivor区的目标使用率,默认50
-XX:+UseG1GC 开启使用G1
-XX:G1HeapRegionSize=n region的大小,1-32M之间,最大2048个
-XX:MaxGCPauseMillis=200 最大停顿时间
-XX:G1NewSizePercent 新生代占比
-XX:G1MaxNewSizePercent 新生代最大占比
-XX:G1ReservePercent=10 保留的内存占比以避免to区的溢出
-XX:ParallelGCThreads=n 并行的线程数,会停止应用的
-XX:ConcGCThreads=n 并发线程数,和应用程序一起执行的,默认是1/4的-XX:ParallelGCThreads=n

样例,针对JDK1.7

-server -Xmx4g -Xms4g -Xmn256m 
-XX:PermSize=128m 
-Xss256k 
-XX:+DisableExplicitGC 
-XX:+UseConcMarkSweepGC 
-XX:+CMSParallelRemarkEnabled 
-XX:+UseCMSCompactAtFullCollection 
-XX:LargePageSizeInBytes=128m 
-XX:+UseFastAccessorMethods 
-XX:+UseCMSInitiatingOccupancyOnly 
-XX:CMSInitiatingOccupancyFraction=70

参数解释:

  • -server VM有两种运行模式Server与Client,两种模式的区别在于,Client模式启动速度较快,Server模式启动较慢;但是启动进入稳定期长期运行之后Server模式的程序运行速度比Client要快很多;
  • -Xmx4g 最大堆大小;
  • -Xms4g 初始堆大小;
  • -Xmn256m 堆中年轻代大小;
  • -XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;
  • XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4;
  • -Xss 每个线程的Stack大小;
  • -XX:+DisableExplicitGC,这个参数作用是禁止代码中显示调用GC。代码如何显示调用GC呢,通过System.gc()函数调用。如果加上了这个JVM启动参数,那么代码中调用System.gc()没有任何效果,相当于是没有这行代码一样;
  • -XX:+UseConcMarkSweepGC 并发标记清除(CMS)收集器,CMS收集器也被称为短暂停顿并发收集器;
  • -XX:+CMSParallelRemarkEnabled 降低标记停顿;
  • -XX:+UseCMSCompactAtFullCollection: 使用并发收集器时,开启对年老代的压缩;
  • -XX:LargePageSizeInBytes 指定Java heap的分页页面大小;
  • -XX:+UseFastAccessorMethods 原始类型的快速优化;
  • -XX:+UseCMSInitiatingOccupancyOnly  使用手动定义的初始化大小开始CMS收集;
  • -XX:CMSInitiatingOccupancyFraction 使用cms作为垃圾回收使用70%后开始CMS收集;

对于Tomcat,在tomcat的bin目录下的catalina.sh中设置jvm参数:

JAVA_OPTS=”-server -Xmx4g -Xms4g -Xmn256m -XX:PermSize=128m -Xss256k 
-XX:+DisableExplicitGC 
-XX:+UseConcMarkSweepGC 
-XX:+CMSParallelRemarkEnabled 
-XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m 
-XX:+UseFastAccessorMethods 
-XX:+UseCMSInitiatingOccupancyOnly 
-XX:CMSInitiatingOccupancyFraction=70”

并行垃圾收集器:多个GC线程可以同时收集;

并发垃圾收集器:多个GC线程和应用线程可以同时工作;

代码优化建议:

  • 尽量重用对象,不要循环创建对象,比如for循环字符串拼接;
  • 容器类初始化的时候建议指定长度;list、map -->扩容影响性能;
  • ArrayList随机访问快,添加删除慢,LinkedList添加删除快,随机访问慢;
  • 集合遍历尽量减少重复计算集合size(),使用变量存储;
  • 使用Entry遍历Map;for(Map.entry entry : map.entrySet()) {}
  • 大数组复制采用System.arraycopy(); -->它是native方法
  • 尽量使用基本类型而不使用包装类型;int a = 10; 拆箱使用了.valueOf();
  • 不要手动调用System.gc();
  • 及时释放对象的引用防止内存泄漏,user[i] = null;-->数组、map等要注意;
  • 多用局部变量少用成员变量,减小变量的作用域;
  • 减少同步锁的作用范围,synchronized;
  • 使用ThreadLocal缓存线程不安全的对象;
  • 尽量使用延迟加载;
  • 减少使用反射;
  • 多采用连接池、线程池、对象池 (commons-pool.jar)、缓存等;
  • 及时释放连接资源,数据库连接、IO流、socket连接等;
  • 日志输出生产环境注意级别,日志参数使用占位符而不是拼接;
  • logger.info(“user id =”+ id);
  • logger.info(“user id = {}”, id);

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值