调优基本概念

在调整JVM性能时,通常有三个组件需要考虑:

  1. 堆大小调整
  2. 垃圾收集器调整
  3. JIT编译器

大多数调优选项都与调整堆大小和选择合适的垃圾收集器有关,JIT编译器对性能也有很大影响,但很少需要对其进行调优,尤其是针对较新版本的JVM。

通常,在进行Java程序调优的时候,会重点关注两个主要指标:

  • 响应性:应用程序对请求进行响应的速度,对于专注响应性的应用程序,长时间的暂停是不可接受的,需要在最短时间内做出响应
  • 吞吐量:侧重于在特定时间内最大化应用程序的工作量,对于专注于吞吐量的应用程序,符合要求的暂停是可以接受的。

JVM本身是在不断优化的,系统瓶颈的核心还是在于应用代码,更多的情况下还是要专注于应用代码的优化。

常用JVM参数

参数 描述
-XX:+AlwaysPreTouch JVM启动时分配内存,堆的每个页面都在初始化期间按需置零,而不是在应用程序执行期间递增
-XX:Errorfile = filename 错误日志
-XX:+TraceClassLoading 跟踪类加载信息
-XX:+PrintClassHistogram 按下Ctrl+Break后打印类信息
-Xmx -Xms 最大堆 最小堆
-xx:permSize 永久代大小
-xx:metaspaceSize 元数据空间大小
-XX:+HeapDumpOnOutOfMemoryError 当抛出OOM时进行HeapDump
-XX:+HeapDumpPath OOM时堆导出的路径
-XX:OnOutOfMemoryError 当发生OOM时执行用户指定的命令

命令: java -XX:+PrintFlagsFinal -version 会 打印所有的-XX参数及其默认值

GC调优思路

  1. 分析场景,如:启动速度慢,偶尔出现响应慢于平均水平或出现卡顿
  2. 确定目标,如:内存占用,低延时,吞吐量
  3. 收集日志,如:通过参数配置收集GC日志,通过JDK工具查看GC状态
  4. 分析日志,如:使用工具辅助分析日志,查看GC次数,GC时间
  5. 调整参数,如:切换垃圾收集器或者调整垃圾收集器参数

常用GC参数

参数 描述
-XX:ParallelGCThreads 并行GC线程数量
-XX:ConcGcThreads 并发GC线程数量
-XX:MaxGCPauseMillis 最大停顿时间,单位毫秒,GC尽力保证回收时间不超过设定值
-XX:GCTimeRatio 垃圾收集时间占总时间的比值,取值0-100,默认99,即最大允许1%的时间做GC
-XX:SurvivorRatio 设置eden区大小和survivor区大小的比例,8表示两个survivor:eden=2:8,即一个survivor占年轻代的1/10
-XX:NewRatio 新生代和老年代的比,4表示新生代:老年代=1:4,即年轻代占堆的1/5
-verbose:gc,-XX:+PrintGC 打印GC的简要信息
-XX:+PrintGCDetails 打印GC详细信息(JDK9之后不再使用)
-XX:+PrintGCTimeStamps 打印GC发生的时间戳(JDK9之后不再使用)
-Xloggc:log/gc.log 指定GC log的位置,以文件输出
-XX:PrintHeapAtGC 每次GC后都打印堆信息

垃圾收集器Parallel参数调优

Parallel垃圾收集器在JDK8中是JVM默认的垃圾收集器,它是以吞吐量优先的垃圾收集器。其可调节的参数如下:

参数 描述
-XX:+UseParallelGC 新生代使用并行垃圾收集器
-XX:+UseParallelOldGC 老年代使用并行垃圾收集器
-XX:ParallelGCThreads 设置用于垃圾回收的线程数
-XX:+UseAdaptiveSizePolicy 打开自适应GC策略

垃圾收集器CMS参数调优

CMS垃圾收集器是一个响应时间优先的垃圾收集器,Parallel收集器无法满足应用程序延迟要求时再考虑使用CMS垃圾收集器,从JDK9开始CMS收集器已不建议使用,默认用的是G1垃圾收集器。

参数 描述
-XX:+UseConcMarkSweepGC 新生代使用并行收集器,老年代使用CMS+串行收集器
-XX:+UseParNewGC 新生代使用并行收集器,老年代CMS收集器默认开启
-XX:CMSInitiatingOccupanyFraction 设置触发GC的阈值,默认68%,如果内存预留空间不够,就会引起concurrent mode failure
-XX:+UseCMSCompactAtFullCollection Full GC后,进行一次整理,整理过程是独占的,会引起停顿时间变长
-XX:+CMSFullGCsBeforeCompaction 设置进行几次Full GC后进行一次碎片整理
-XX:+CMSClassUnloadingEnabled 允许对类元数据进行回收
-XX:+UseCMSInitiatingOccupanyOnly 表示只在达到阈值的时候才进行CMS回收
-XX:+CMSIncrementalMode 使用增量模式,比较适合单CPU

垃圾收集器G1参数调优

G1收集器是一个兼顾吞吐量和响应时间的收集器,如果是大堆(如堆的大小超过6GB),堆的使用率超过50%,GC延迟要求稳定且可预测的低于0.5秒,建议使用G1收集器。

参数 描述
-XX:G1HeapRegionSize 设置Region大小,默认heap/2000
-XX:G1MixedGCLiveThresholdPercent 老年代依靠Mixed GC, 触发阈值
-XX:G1OldSetRegionThresholdPercent 定多包含在一次Mixed GC中的Region比例
-XX:+ClassUnloadingWithConcurrentMark G1增加默认开启,在并发标记阶段结束后,JVM即进行类型卸载
-XX:G1NewSizePercent 新生代的最小比例
-XX:G1MaxNewSizePercent 新生代的最大比列
-XX:G1MixedGCCountTraget Mixed GC数量控制

调优示例

示例代码:

@SpringBootApplication
public class SpringBootDemoApplication { public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
Executors.newScheduledThreadPool(1)
.scheduleAtFixedRate(
() -> {
new Thread(
() -> {
for (int i = 0; i < 150; i++) {
try {
byte[] temp = new byte[1024 * 512];
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
})
.start();
},
100,
100,
TimeUnit.MILLISECONDS);
}
}

GC分析主要查看GC导致的Stop The World的时间,它会导致程序的延时增加。

示例代码运行的时候建议指定其堆内存的最大值,启动时添加JVM参数-Xmx1024m。程序运行起来之后可以利用jps或者jcmd产看运行的程序进程号。

拿到进程号之后利用jstat命令查看GC信息,如动态监控GC统计信息,间隔1000毫秒统计一次,每10行数据后输出列标题:

上述两个步骤也可以合并成一个 jstat -gc -h10 $(jcmd | grep “com.example.springbootdemo.SpringBootDemoApplication” | awk ‘{print $1}’) 1000

当然除了动态监控GC信息,也可以将GC日志信息打印到文件,然后利用GC分析工具进行分析。
在程序启动时添加JVM参数”-Xmx1024m -Xloggc:/gc.log“,则可以可以将GC日志打印到gc.log文件,然后可以利用GCViewer工具辅助分析GC日志文件,参考地址:https://github.com/chewiebug/GCViewer

GCViewer下载后双击gcviewer-x.xx-SNAPSHOT.jar文件即可运行,然后将gc.log日志文件导入即可观察GC信息。

GC调优之前,我们需要了解当前JVM参数的信息。命令 java -XX:+PrintFlagsFinal -version 会打印所有的JVM参数,如需查看指定参数,如查看UseAdaptiveSizePolicy的值可以使用 java -XX:+PrintFlagsFinal -version | grep UseAdaptiveSizePolicy

调整-XX:ParallelGCThreads的值可以指定GC并发的线程数,如在JVM启动参数中可以添加 “-Xmx1024m -XX:ParallelGCThreads=4”,调节GC并发的线程数,观察GC的信息,如Full GC次数FGC,Full GC的总时间FGCT,GC的总时间GCT等进行调优。

同样我们可以在JVM启动参数中指定-XX:MaxGCPauseMills,使用G1收集器-XX:+UseG1GC等,调节JVM启动参数,收集GC日志,更具监控进行相应的调节,进而找到最优值。

JVM参数及调优的更多相关文章

  1. [JVM教程与调优] 什么是JVM运行时参数?

    我们接着上一章节[JVM教程与调优] JVM都有哪些参数类型?的内容继续讲解,这章我们来介绍一下:如何查看JVM运行时参数.这一点十分重要,因为我们在进行JVM参数调优的时候,我们首先得知道目前系统运 ...

  2. Java系列笔记(4) - JVM监控与调优

    目录 参数设置收集器搭配启动内存分配监控工具和方法调优方法调优实例     光说不练假把式,学习Java GC机制的目的是为了实用,也就是为了在JVM出现问题时分析原因并解决之.通过学习,我觉得JVM ...

  3. JVM监控与调优

    目录 参数设置收集器搭配启动内存分配监控工具和方法调优方法调优实例     转:http://www.cnblogs.com/zhguang/p/java-jvm-gc.html光说不练假把式,学习J ...

  4. [java] JVM监控与调优

    原文出处:http://www.cnblogs.com/zhguang/p/java-jvm-gc.html   光说不练假把式,学习Java GC机制的目的是为了实用,也就是为了在JVM出现问题时分 ...

  5. Tomcat性能调优-JVM监控与调优

    参数设置 在Java虚拟机的参数中,有3种表示方法用"ps -ef |grep "java"命令,可以得到当前Java进程的所有启动参数和配置参数: 标准参数(-),所有 ...

  6. spark submit参数及调优

    park submit参数介绍 你可以通过spark-submit --help或者spark-shell --help来查看这些参数.   使用格式:  ./bin/spark-submit \   ...

  7. JVM监控和调优常用命令工具总结

    JVM监控和调优 在Java应用和服务出现莫名的卡顿.CPU飙升等问题时总是要分析一下对应进程的JVM状态以定位问题和解决问题并作出相应的优化,在这过程中Java自带的一些状态监控命令和图形化工具就非 ...

  8. spark submit参数及调优(转载)

    spark submit参数介绍 你可以通过spark-submit --help或者spark-shell --help来查看这些参数. 使用格式:  ./bin/spark-submit \ -- ...

  9. Java启动参数及调优

    java启动参数共分为三类: 其一是标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容:其二是非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且 ...

随机推荐

  1. python爬虫遇到会话存储sessionStorage

    记录一次爬虫生成链接过程中遇到的sessionStorage存储数据 1.简介 sessionStorage 是HTML5新增的一个会话存储对象,用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标 ...

  2. 彻底理解CORS跨域原理

    背景 现在的前端开发中都是前后端分离的开发模式,数据的获取并非同源,所以跨域的问题在我们日常开发中特别常见.其实这种资料网上也是一搜一大堆,但是都不够全面,理解起来也不够透彻.这篇文章就结合具体的示例 ...

  3. mybatis入门百分百

    今天重新返回来看自己的mybatis,总结了一些更好入门的办法,下面用最简单的方法带领大家入门. 此处先引入类包的关系图片 1.构建一个==普通==maven项目 构建好之后向pom.xml添加一下依 ...

  4. TouchListener PK OnTouchEvent + 多点触碰

    1.基于监听的TouchListener 代码示例: 实现效果图: 实现代码: main.xml <RelativeLayout xmlns:android="http://schem ...

  5. CocosCreator 快速开发推箱子游戏,附代码

    游戏总共分为4个功能模块: - 开始游戏(menuLayer) - 关卡选择(levelLayer) - 游戏(gameLayer) - 游戏结算(gameOverLayer) Creator内组件效 ...

  6. WPF写圆形头像,带消息提醒图标

    <DockPanel VerticalAlignment="Top" HorizontalAlignment="Stretch" Margin=" ...

  7. AOP框架Dora.Interception 3.0 [2]: 实现原理

    和所有的AOP框架一样,我们必须将正常的方法调用进行拦截,才能将应用到当前方法上的所有拦截器纳入当前调用链.Dora.Interception采用IL Eimit的方式实现对方法调用的拦截,接下来我们 ...

  8. Spring Security 入门(一)

    当你看到这篇文章时,我猜你肯定是碰到令人苦恼的问题了,我希望本文能让你有所收获. 本人几个月前还是 Spring 小白,几个月走来,看了 Spring,Spring boot,到这次的 Spring ...

  9. Linux提权中常见命令大全

    在拿到一个 webshell 之后,大家首先会想到去把自己的权限提升到最高,windows 我们会提升到 SYSTEM 权限,而 Linux 我们会提升到 root 权限,拿在进行 Linux 提权的 ...

  10. Cocos2d-x 学习笔记(8) ActionManager

    1. 概述 ActionManager管理所有的action,调度所有的action,删除指定的action.每个action对应一个node对象,action存储在actions中,actions和 ...