JVM参数及调优
Posted ~无关风月~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM参数及调优相关的知识,希望对你有一定的参考价值。
JVM控制参数
服务器的 Xmx 和 Xms 设置一般应该设置相同避免每次 GC 后都要调整虚拟机堆的大小
参数 | 含义 | 说明 |
---|---|---|
-XX:InitialHeapSize=100M | 初始化堆大小 | 简写-Xms100M |
-XX:MaxHeapSize=100M | 最大堆大小,默认是物理内存的 1/4 | 简写-Xmx100M |
-XX:NewSize=20M | 新生代最小空间大小 | |
-XX:MaxNewSize=50M | 新生代最大空间大小 | |
-Xmn | 设置堆内新生代的大小 | 相当于设置了相同的-XX:NewSize和-XX:MaxNewSize |
-XX:SurvivorRatio | 两个S区和Eden区的比值 | 比如-XX:SurvivorRatio=8,也就 是(S0+S1):Eden=2:8,也就是一个S占整个新生代的1/10 |
-XX:OldSize=50M | 设置老年代大小 | |
-XXPermSize=8m -XXMaxPermSize=8m | 设置方法区大小 | JDK1.8以后失效 |
-XX:MetaspaceSize=50M | 设置方法区大小 | |
-XX:MaxMetaspaceSize=50M | 设置方法区最大大小 | |
-XX:NewRatio | 新老生代的比值 | 比如-XX:Ratio=4,则表示新生代: 老年代=1:4,也就是新生代占整 个堆内存的1/5 |
-XX:MaxTenuringThreshold=6 | 提升年老代的最大临界值 | 默认值为 15 |
-Xss128k | 设置每个线程可使用的栈空间大小,每个线程都有他自己的 Stack | 经验值是3000-5000最佳 |
-XX:G1HeapWastePercent | 允许的浪费堆空间的占比 | 默认是10%,如果并发标记可回收的空间小于10%,则不会触发 MixedGC。 |
垃圾收集器相关:
参数 | 含义 | 说明 |
---|---|---|
-XX:+UseParallelGC | 使用UseParallelGC | 新生代,吞吐量优先 |
-XX:+UseParallelOldGC | 使用UseParallelOldGC | 老年代,吞吐量优先 |
-XX:+UseConcMarkSweepGC | 使用CMS | 老年代,停顿时间优先 |
-XX:+UseG1GC | 使用G1 | 新生代,老年代,停顿时间优先 |
-XX:MaxGCPauseMillis=200ms | G1最大停顿时间 | 暂停时间不能太小,太小的话就会导致出现G1跟不上垃圾产生的 速度。最终退化成Full GC。所以 对这个参数的调优是一个持续的 过程,逐步调整到最佳状态。 |
-XX:InitiatingHeapOccupancyPercent | 启动并发GC周期时堆内存使用占比 | G1之类的垃圾收集器用它来触发并发GC周期,基于整个堆的使用率,而不只是某一代内存的使用比. 值为 0 则表示”一直执行GC循环”. 默认值为 45. |
-XX:ConcGCThreads=n | 并发垃圾收集器使用的线程数量 | 默认值随JVM运行的平台不同而不同 |
-XX:G1MixedGCLiveThresholdPercent=65 | 混合垃圾回收周期中要包括的旧区域设置占用率阈值 | 默认占用率为 65% |
-XX:G1MixedGCCountTarget=8 | 设置标记周期完成后,对存活数据上限为 G1MixedGCLIveThresholdPercent 的旧区域执行混合垃圾回收的目标次数 | 默认8次混合垃圾回收,混合回收的目标是要控制在此目标次数以内 |
-XX:G1OldCSetRegionThresholdPercent=1 | 描述Mixed GC时,Old Region被加入到CSet中 | 默认情况下,G1只把10%的Old Region加入到CSet中 |
其他:
参数 | 含义 | 说明 |
---|---|---|
-XX:+HeapDumpOnOutOfMemoryError | 启动堆内存溢出打印 | 当JVM堆内存发生溢出时,也就 是OOM,自动生成dump文件 |
-XX:HeapDumpPath=heap.hprof | 指定堆内存溢出打印目录 | 表示在当前目录生成一个 heap.hprof文件 |
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:g1- gc.log | 打印出GC日志 | 可以使用不同的垃圾收集器,对 比查看GC情况 |
-XX:CICompilerCount=3 | 最大并行编译数 | 如果设置大于1,虽然编译速度会提高,但是同样影响系统稳定性,会增加JVM崩溃的可能 |
标准参数
-version
-help
-server
-cp
-X参数
非标准参数,也就是在JDK各个版本中可能会变动
-Xint 解释执行
-Xcomp 第一次使用就编译成本地代码
-Xmixed 混合模式,JVM自己来决定
-XX参数
使用得最多的参数类型
非标准化参数,相对不稳定,主要用于JVM调优和Debug
a.Boolean类型
格式:-XX:[±] +或-表示启用或者禁用name属性
比如:
-XX:+UseConcMarkSweepGC 表示启用CMS类型的垃圾回收器
-XX:+UseG1GC 表示启用G1类型的垃圾回收器
b.非Boolean类型
格式:-XX=表示name属性的值是value 比如:-XX:MaxGCPauseMillis=500
-Xms1000M等价于-XX:InitialHeapSize=1000M
-Xmx1000M等价于-XX:MaxHeapSize=1000M
-Xss100等价于-XX:ThreadStackSize=100
查看参数
java -XX:+PrintFlagsFinal -version > flags.txt
设置参数的常见方式
- 开发工具中设置比如IDEA,eclipse
- 运行jar包的时候:java -XX:+UseG1GC xxx.jar
- web容器比如tomcat,可以在脚本中进行设置
- 通过jinfo实时调整某个java进程的参数(参数只有被标记为manageable的flags可以被实时修改)
JVM调试命令
- jps
JVM Process Status Tool,列出指定系统内所有的HotSpot虚拟机进程。
- jstat
JVM statistics monitoring,用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
- jmap
JVM Memory Map 用于生成 heap dump文件,还可以查询finalize 执行队列、java堆和永久代的详细信息,如当前使用率、当前使用的是哪种收集器等。
- jhat
JVM Heap Analysis Tool 与 jmap 搭配使用,分析jmap生成的dump ,jhat 内置了一个微型html服务器,可以在浏览器查看dump分析结果。
- jstack
stack trace for java 用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程死锁,死循环,请求外部资源导致的长时间等待等
- jinfo
实时查看和调整JVM各项参数。最下面的地方有个参数-Xloggc:,他对应的就是gc log的位置。
JVM调试工具
jdk/bin目录下
-
jconsole
(Java Monitoring and Management Console)是从java5开始,在JDK中自带的java监控和管理控制台,用于对JVM中内存,线程和类等的监控,是一个基于JMX(java management extensions)的GUI性能监测工具。jconsole使用jvm的扩展机制获取并展示虚拟机中运行的应用程序的性能和资源消耗等信息。
VisualVM(从 Oracle JDK 9 开始,VisualVM 已经不再包含在 JDK 安装包中)
VisualVM 是一个工具,它提供了一个可视界面,用于查看 Java 虚拟机上运行的Java 应用程序的详细信息。VisualVM 对 Java Development Kit (JDK) 工具所检索的 JVM 软件相关数据进行组织,并通过一种使您可以快速查看有关多个 Java 应用程序的数据的方式提供该信息。您可以查看本地应用程序以及远程主机上运行的应用程序的相关数据。此外,还可以捕获有关 JVM 软件实例的数据,并将该数据保存到本地系统,以供后期查看或与其他用户共享。 -
VisualVM,JDK发布的功能强大的运行监视和故障处理、性能分析程序。支持插件扩展。包括概述(JVM参数、系统属性)、监视(CPU使用情况、内存信息、类装载图、线程图)、线程监控(各线程运行状态)、VirtualGC(查看堆各部分内存使用情况)、生成查看堆转储快照、Btrace动态日志跟踪,在字节码层面上对代码进行跟踪,编写代码获取程序方法的参数、返回值等信息(在运行环境特别有用)。
第三方:
- MAT ,Eclipse Memory Analysis Tools ,eclipse插件
- gcviewer,用gcviewer 打开gc log可以很直观的查看gc log
这里有一个相对特殊的部分,就是是堆外内存中的直接内存,前面的工具基本不适用,可以使用 JDK 自带的 Native Memory Tracking(NMT)特性,它会从 JVM 本地内存分配的角度进行解读。
JVM调优案例
场景:60s 秒杀活动
预估:订单数 3000/s
预算:3台4核8G服务器
每台服务器:8G内存,分配4-6G给堆(最多不要超过总内存的80%)。
我们按照分4G给堆算:新生代分1333M,老年代2667M。
新生代 Eden区 = 1333M * 0.8 = 1066M。
三台机器做负载均衡,每台机器按要承担 1200/s 算。
一个订单对象Order占多大内存=对象头+实例数据+对齐填充=1KB 算。
订单会关联查商品、购物车等,假设一共关联20个对象,1KB * 20 * 1200 = 24M,及一个服务器一秒钟会产生24M大小的对象。
堆内存第一次使用时:1066M/24M = 44,及第44秒后会触发yong GC ,可能产生对象晋升,对象晋升可能产生Full GC。
增大新生代到3000M,3000M * 0.8 / 24 = 100 ,可以抗100s ,满足业务需求。
本方式不适用于G1,G1 不要设置新生代大小,G1的新生代和老年代会动态变化,固定的新生代大小会阻碍设置的停顿时间的目标。
以上是关于JVM参数及调优的主要内容,如果未能解决你的问题,请参考以下文章