jvm - 常用调优启动参数配置

jvm - 常用调优启动参数配置,第1张

可以看到堆内存为2G,新生代为768M老年代为1280M,新生代采用ParNew收集器

-XX:+UseConcMarkSweepGC:新生代使用ParNew回收器,老年代使用CMS

线程栈为512k(默认1024k调小可以增加创建线程数,增加并发量)

同时打印 GC 详细信息和打印 GC 发生时间,当发生OOM时,Dump文件到指定路径

栈空间参数设置

-Xss: 设置线程的最大栈空间,栈空间越大,方法的递归深度越大

方法区参数设置(方法区大小的参数设置跟jdk版本相关)

jdk1.6,jdk1.7设置方法区永久代的大小

-XX:PermSize=5M

-XX:MaxPermSize=5M 最大永久代的大小默认是64M

jdk1.8及以上,永久代被移除,取而代之的是元数据区,元数据区是一块堆外的直接内存

如果不指定大小,那么会耗尽所有可用的系统内存

-XX:MaxMetaspaceSize=60M 设置最大元数据的大小

堆设置

-Xms:初始堆大小

-Xmx:最大堆大小

-Xmn:设置新生代大小,设置较大的新生代大小会减小老年代大小,新生代的大小一般为堆空间的1/3

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

-XX:NewRatio=n:设置年轻代和年老代的比值(老年代/新生代)。如:为3,表示年轻代与年老代比值为1:3

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

-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。

-Xmn,-XX:NewSize/-XX:MaxNewSize,-XX:NewRatio 3组参数都可以影响年轻代的大小,混合使用的情况下,优先级是什么?

1.高优先级:-XX:NewSize/-XX:MaxNewSize

2.中优先级:-Xmn(默认等效 -Xmn=-XX:NewSize=-XX:MaxNewSize=?)

3.低优先级:-XX:NewRatio

推荐使用-Xmn参数,原因是这个参数简洁,相当于一次设定 NewSize/MaxNewSIze而且两者相等,适用于生产环境。

-Xmn 配合 -Xms/-Xmx,即可将堆内存布局完成 -Xmn参数是在JDK 1.4 开始支持

下面两个参数配合使用,当系统发生堆空间不足时,会导出整个堆的信息,且导出到指定的文件中去,后面用MAT工具分析

-XX:HeapDumpOnOutOfMemoryError

-XX:HeapDumpPath=d:/a.dump

直接内存配置

-XX:MaxDirectMemorySize

设置直接内存大小,如果不设置,默认值为最大堆空间,即-Xmx指定的大小,当达到指定值时,

会触发垃圾回收,如果回收后也无法释放空间,那么将会抛出OOM

-XX:+UseSerialGC:新生代,老年代都使用串行收集器

-XX:+UseParNewGC:新生代使用ParNew收集器,老年代使用串行收集器Serial

(jdk9,10已经废除,因为ParNew只能和CMS收集器配合使用,而jdk9,10使用的默认收集器是G1)

-XX:+UseParallelGC:新生代使用ParallelGC,老年代使用串行收集器Serial

-XX:+UseParallelGC:新生代使用ParallelGC回收器,老年代使用串行回收器Serial

-XX:+UseParallelOldGC:新生代使用ParallelGC回收器,老年代使用ParallelOldGc回收器

两个重要参数

-XX:MaxGCPasuseMillis:设置最大垃圾回收停顿时间,设置的过小,可能导致垃圾回收频率加大

-XX:GCTimeRatio:设置吞吐量大小,取值范围为0-100,系统回收垃圾的停顿时间花费不超过1/(1+n)%

设置线程数量

-XX:ParallelGCThreads

-XX:+UseConcMarkSweepGC:新生代使用ParNew回收器,老年代使用CMS

CMS默认启动的并发线程数量为(parallelGCTheads+3)/4

设置并发线程数

-XX:ConcGCThreads=n

-XX:ParallelGCThreads=n

设置老年代空间使用率达到多少时执行CMS垃圾回收

-XX:CMSInitiatingOccupancyFraction 默认值为68

碎片整理参数,如果碎片不整理,可能造成没达到阈值就会触发老年代垃圾回收

-XX:+UseCMSCompactAtFullCollection :在CMS垃圾收集完成之后,进行一次内存碎片整理

-XX:+CMSFullGCsBeforeCompaction=n :在n次CMS回收后进行一次内存碎片整理

使用CMS回收方法去的perm区,默认情况下,还需要触发一次FullGC

-XX:+CMSClassUnloadingEnabled

XX:UseG1GC 开启G1垃圾收集器

两个重要的参数

-XX:MaxGcPasuseMillis :指定目标最大停顿时间,如果停顿的时间过小,一次收集的区域数量也会变小

就会增加FullGC的可能

-XX:parallelGCThreads :设置并行回收的GC线程数量

-XX:InitiatingHeapOccupancyPercent :设置整个堆使用率达到多少时,触发并发标记的执行,默认是45

-XX:+PrintGC 在程序运行期间,只要遇到GC,就会打印GC情况

占用大小->gc后大小 GC消耗时间

jdk9,jdk10默认使用G1收集器,所以打印GC参数不同

-Xlog:gc

-XX:+PrintGCDetails 打印GC详细信息(JDK8,9,10建议使用-Xlog:gc*)

-XX:+PrintGCTimeStamps 打印分析GC发生的时间

-XX:+PrintGCApplicationConcurrentTime 打印应用程序的执行时间

-XX:+PrintGCApplicationStoppedTime 打印GC产生停顿的时间

-Xloggc:/usr/local/log/gc.log 让gc日志打印在log文件夹下的gc文件中,因为默认情况下gc日志在控制台输出

栈上分配,逃逸分析(方法内的变量被外部引用)

允许对象直接在栈上进行分配,随线程停止而销毁,这样做可以加快分配速度,减少GC次数

栈空间较小,所以不适合大对象的栈上分配

-XX:+DoEscapeAnalysis 启用逃逸分析

-XX:+EliminateAllocations 开启标量替换(默认打开),允许对象打散分配在栈上

比如对象拥有id和name两个字段,那么这两个字段将会被视为两个独立的变量进行分配。

对象晋升

-MaxTenuringThreshold=n ,当对象经历了多少次GC次数后进入老年代

注意:大对象直接晋升到老年代

-PretenureSizeThreshold=n 这里的单位是字节,新生对象大于这个值的时候,会直接分配到老年代

1、对存活对象标注时间过长:比如重载了Object类的Finalize方法,导致标注Final Reference耗时过长;或者String.intern方法使用不当,导致YGC扫描StringTable时间过长。

2、长周期对象积累过多:比如本地缓存使用不当,积累了太多存活对象;或者锁竞争严重导致线程阻塞,局部变量的生命周期变长

当Eden区空间不足时,就会触发YGC。结合新生代对象的内存分配看下详细过程:

1、新对象会先尝试在栈上分配,如果不行则尝试在TLAB分配,否则再看是否满足大对象条件要在老年代分配,最后才考虑在Eden区申请空间。

2、如果Eden区没有合适的空间,则触发YGC。

3、YGC时,对Eden区和From Survivor区的存活对象进行处理,如果满足动态年龄判断的条件或者To Survivor区空间不够则直接进入老年代,如果老年代空间也不够了,则会发生promotion failed,触发老年代的回收。否则将存活对象复制到To Survivor区。

4、此时Eden区和From Survivor区的剩余对象均为垃圾对象,可直接抹掉回收。

此外,老年代如果采用的是CMS回收器,为了减少CMS Remark阶段的耗时,也有可能会触发一次YGC,这里不作展开。

大多数情况下,对象直接在年轻代中的Eden区进行分配,如果Eden区域没有足够的空间,那么就会触发YGC(Minor GC),YGC处理的区域只有新生代。因为大部分对象在短时间内都是可收回掉的,因此YGC后只有极少数的对象能存活下来,而被移动到S0区(采用的是复制算法)。当触发下一次YGC时,会将Eden区和S0区的存活对象移动到S1区,同时清空Eden区和S0区。当再次触发YGC时,这时候处理的区域就变成了Eden区和S1区(即S0和S1进行角色交换)。每经过一次YGC,存活对象的年龄就会加1。

下面4种情况,对象会进入到老年代中:

当晋升到老年代的对象大于了老年代的剩余空间时,就会触发FGC(Major GC),FGC处理的区域同时包括新生代和老年代。除此之外,还有以下4种情况也会触发FGC:

有时候我们需要设定maven环境下的JVM参数,以便通过maven执行的命令或启动的系统能得到它们需要的参数设定。比如:当我们使用jetty:run启动jetty服务器时,在进行热部署时会经常发生:java.lang.OutOfMemoryError: PermGen space问题,这时我们需要增大JVM参数MaxPermSize的值。再者,当我们需要进行远程调试时,也需要设置监听端口。maven配置jvm参数的地方是%M2_HOME%/bin/mvn.bat文件,这是启动Maven的脚本文件,在该文件中你能看到有一行注释为:\x0d\x0a@REM set MAVEN_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\x0d\x0a.通过添加set MAVEN_OPTS可以为maven设定jvm参数了。比如:\x0d\x0a1.建立远程调试,端口为:4000的设定为:\x0d\x0aset MAVEN_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4000\x0d\x0a注意:suspend最好设定为n.设定上述参数后,在eclipse中新建远程调试,设置端口为4000,这样通过jetty:run启动系统时就可以进行远程调试了。\x0d\x0a2.解决自动热部署时java.lang.OutOfMemoryError: PermGen space问题解决这一问题只需要增大PermGen区,默认为 64m,设置方法为:set MAVEN_OPTS=-XX:MaxPermSize=128M

-Xint

设置jvm以解释模式运行,所有的字节码将被直接执行,而不会编译成本地码。

-Xbatch

关闭后台代码编译,强制在前台编译,编译完成之后才能进行代码执行;

默认情况下,jvm在后台进行编译,若没有编译完成,则前台运行代码时以解释模式运行。

-Xbootclasspath:bootclasspath

让jvm从指定路径(可以是分号分隔的目录、jar、或者zip)中加载bootclass,用来替换jdk的rt.jar;若非必要,一般不会用到;

-Xbootclasspath/a:path

将指定路径的所有文件追加到默认bootstrap路径中;

-Xbootclasspath/p:path

让jvm优先于bootstrap默认路径加载指定路径的所有文件;

-Xcheck:jni

对JNI函数进行附加check;此时jvm将校验传递给JNI函数参数的合法性,在本地代码中遇到非法数据时,jmv将报一个致命错误而终止;使用该参数后将造成性能下降,请慎用。

-Xfuture

让jvm对类文件执行严格的格式检查(默认jvm不进行严格格式检查),以符合类文件格式规范,推荐开发人员使用该参数。

-Xnoclassgc

关闭针对class的gc功能;因为其阻止内存回收,所以可能会导致OutOfMemoryError错误,慎用;

-Xincgc

开启增量gc(默认为关闭);这有助于减少长时间GC时应用程序出现的停顿;但由于可能和应用程序并发执行,所以会降低CPU对应用的处理能力。

-Xloggc:file

与-verbose:gc功能类似,只是将每次GC事件的相关情况记录到一个文件中,文件的位置最好在本地,以避免网络的潜在问题。

若与verbose命令同时出现在命令行中,则以-Xloggc为准。

-Xmsn

指定jvm堆的初始大小,默认为物理内存的1/64,最小为1M;可以指定单位,比如k、m,若不指定,则默认为字节。

-Xmxn

指定jvm堆的最大值,默认为物理内存的1/4或者1G,最小为2M;单位与-Xms一致。

-Xprof

跟踪正运行的程序,并将跟踪数据在标准输出输出;适合于开发环境调试。

-Xrs

减少jvm对 *** 作系统信号(signals)的使用,该参数从1.3.1开始有效;

从jdk1.3.0开始,jvm允许程序在关闭之前还可以执行一些代码(比如关闭数据库的连接池),即使jvm被突然终止;

jvm 关闭工具通过监控控制台的相关事件而满足以上的功能;更确切的说,通知在关闭工具执行之前,先注册控制台的控制handler,然后对 CTRL_C_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and

CTRL_SHUTDOWN_EVENT这几类事件直接返回true。

但如果jvm以服务的形式在后台运行(比如servlet引擎),他能接 收CTRL_LOGOFF_EVENT事件,但此时并不需要初始化关闭程序;为了避免类似冲突的再次出现,从jdk1.3.1开始提供-Xrs参数;当此 参数被设置之后,jvm将不接收控制台的控制handler,也就是说他不监控和处理CTRL_C_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, or

CTRL_SHUTDOWN_EVENT事件。

-Xssn

设置单个线程栈的大小,一般默认为512k。

上面这些参数中,比如-Xmsn、-Xmxn……都是我们性能优化中很重要的参数;

-Xprof、-Xloggc:file等都是在没有专业跟踪工具情况下排错的好手;

在上一小节中提到的关于JProfiler的配置中就使用到了-Xbootclasspath/a:path;

非Stable参数

前面我们提到用-XX作为前缀的参数列表在jvm中可能是不健壮的,SUN也不推荐使用,后续可能会在没有通知的情况下就直接取消了;但是由于这些参数中的确有很多是对我们很有用的,比如我们经常会见到的-XX:PermSize、-XX:MaxPermSize等等;

下面我们将就Java HotSpot VM中-XX:的可配置参数列表进行描述;

这些参数可以被松散的聚合成三类:

行为参数(Behavioral Options):用于改变jvm的一些基础行为;

性能调优(Performance Tuning):用于jvm的性能调优;

调试参数(Debugging

Options):一般用于打开跟踪、打印、输出等jvm参数,用于显示jvm更加详细的信息;

由于sun官方文档中对各参数的描述也都非常少(大多只有一句话),而且大多涉及OS层面的东西,很难描述清楚,所以以下是挑选了一些我们开发中可能会用得比较多的配置项,若需要查看所有参数列表,可以点击HotSpot VM Specific

Options.查看原文;

首先来介绍行为参数:

参数及其默认值

描述

-XX:-DisableExplicitGC

禁止调用System.gc();但jvm的gc仍然有效

-XX:+MaxFDLimit

最大化文件描述符的数量限制

-XX:+ScavengeBeforeFullGC

新生代GC优先于Full GC执行

-XX:+UseGCOverheadLimit

在抛出OOM之前限制jvm耗费在GC上的时间比例

-XX:-UseConcMarkSweepGC

对老生代采用并发标记交换算法进行GC

-XX:-UseParallelGC

启用并行GC

-XX:-UseParallelOldGC

对Full GC启用并行,当-XX:-UseParallelGC启用时该项自动启用

-XX:-UseSerialGC

启用串行GC

-XX:+UseThreadPriorities

启用本地线程优先级

上面表格中黑体的三个参数代表着jvm中GC执行的三种方式,即串行、并行、并发;

串行(SerialGC)是jvm的默认GC方式,一般适用于小型应用和单处理器,算法比较简单,GC效率也较高,但可能会给应用带来停顿;

并行(ParallelGC)是指GC运行时,对应用程序运行没有影响,GC和app两者的线程在并发执行,这样可以最大限度不影响app的运行;

并发(ConcMarkSweepGC)是指多个线程并发执行GC,一般适用于多处理器系统中,可以提高GC的效率,但算法复杂,系统消耗较大;

性能调优参数列表:

参数及其默认值

描述

-XX:LargePageSizeInBytes=4m

设置用于Java堆的大页面尺寸

-XX:MaxHeapFreeRatio=70

GC后java堆中空闲量占的最大比例

-XX:MaxNewSize=size

新生成对象能占用内存的最大值

-XX:MaxPermSize=64m

老生代对象能占用内存的最大值

-XX:MinHeapFreeRatio=40

GC后java堆中空闲量占的最小比例

-XX:NewRatio=2

新生代内存容量与老生代内存容量的比例

-XX:NewSize=2.125m

新生代对象生成时占用内存的默认值

-XX:ReservedCodeCacheSize=32m

保留代码占用的内存容量

-XX:ThreadStackSize=512

设置线程栈大小,若为0则使用系统默认值

-XX:+UseLargePages

使用大页面内存

我们在日常性能调优中基本上都会用到以上黑体的这几个属性;

调试参数列表:

参数及其默认值

描述

-XX:-CITime

打印消耗在JIT编译的时间

-XX:ErrorFile=./hs_err_pid.log

保存错误日志或者数据到文件中

-XX:-ExtendedDTraceProbes

开启solaris特有的dtrace探针

-XX:HeapDumpPath=./java_pid.hprof

指定导出堆信息时的路径或文件名

-XX:-HeapDumpOnOutOfMemoryError

当首次遭遇OOM时导出此时堆中相关信息

-XX:

出现致命ERROR之后运行自定义命令

-XX:OnOutOfMemoryError=""

当首次遭遇OOM时执行自定义命令

-XX:-PrintClassHistogram

遇到Ctrl-Break后打印类实例的柱状信息,与jmap -histo功能相同

-XX:-PrintConcurrentLocks

遇到Ctrl-Break后打印并发锁的相关信息,与jstack -l功能相同

-XX:-PrintCommandLineFlags

打印在命令行中出现过的标记

-XX:-PrintCompilation

当一个方法被编译时打印相关信息

-XX:-PrintGC

每次GC时打印相关信息

-XX:-PrintGC Details

每次GC时打印详细信息

-XX:-PrintGCTimeStamps

打印每次GC的时间戳

-XX:-TraceClassLoading

跟踪类的加载信息

-XX:-TraceClassLoadingPreorder

跟踪被引用到的所有类的加载信息

-XX:-TraceClassResolution

跟踪常量池

-XX:-TraceClassUnloading

跟踪类的卸载信息

-XX:-TraceLoaderConstraints

跟踪类加载器约束的相关信息


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11109541.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-13
下一篇 2023-05-13

发表评论

登录后才能评论

评论列表(0条)

保存