常见的JVM参数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常见的JVM参数相关的知识,希望对你有一定的参考价值。
参考技术A -XX:MaxTenuringThreshold :对象晋升老年代的阈值, 默认值15(并不是绝对的,如果在Survivor空间中相同年龄所有对象大小的综合大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代) <br /> -XX:MaxPermSize~~ :永久代大小<br /> -XX:MaxDirectMemorySize :直接内存大小, 默认与-Xmx一致 <br /> -XX:+/-UseTLAB :是否开启TLAB<br /> -XX:MaxMetaspace =256m:元数据区, 默认为无限大,受Java进程所使用的内存影响 <br /> -XX:FieldsAllocationStyle :对象内存分布中的实例数据区域的存储顺序<br /> -XX:CompactFields=true :由于HotSpot在分配对象实例数据时相同大小的字段总是被分配到一起存储,在满足这个条件下因此父类中定义的变量会出现在子类之前,开启此参数那子类中较小的变量也允许插入父类变量的空隙中,以节省一点空间<br /> -XX:+UseCondCardMark :是否开启JVM卡表条件判断,尽量减少伪共享带来的性能损耗<br /> -XX:MaxGCPauseMillis (毫秒 >0) :控制最大垃圾收集停顿时间, 默认值200 <br /> -XX:ParallelGCThreads=NUM :垃圾收集并行执行线程数,默认为CPU的核数<br /> -XX:+UseAdaptiveSizePolicy :是否开启自适应调节策略, JDK8默认开启 <br /> -XX:SurvivorRatio :Eden和Survivor区的比例<br /> -XX:PretenureSizeThreshold :晋升老年代对象大小,超过指定大小直接在老年代分配, 默认为0 <br /> -XX:+PrintGCDetails :打印GC详细日志<br /> -XX:+PrintHeapAtGC :打印每次GC前后堆、方法区可用容量变化<br /> -XX:+PrintGCApplicationConcurrentTime :查看GC过程中用户线程并发时间<br /> -XX:+PrintGCApplicationStoppedTime :查看GC过程中用户线程停顿时间<br /> -XX:+PrintFlagsFinal :查看JVM参数的默认值
<a name="nkixU"></a>
CMS相关见文章 <br />- XX:+UseConMarkSweepGC :开启使用CMS垃圾收集器,新生代使用ParNew 老年代使用CMS<br /> -XX:CMSInitiatingOccupancyFraction=70 :CMS垃圾收集器的回收阈值(老年代),JDK5及之前默认为68%,JDK6之后调整为92%。<br /> -XX:+UseCMSInitiatingOccupancyOnly :与XX:CMSInitiatingOccupancyFraction配合使用,只是用设定的回收阈值(上面指定的70%),如果不指定,JVM仅在第一次使用设定值,后续则自动调整。<br /> -XX:+/-CMSPrecleaningEnabled :开启/关闭CMS并发预清理。<br />
<br /> -XX:CMSScheduleRemarkEdenSizeThreshold :CMS可取消并发预处理阶段开启条件-->默认为2M<br /> -XX:CMSMaxAbortablePrecleanLoops :CMS可取消并发预处理阶段取消条件-->循环次数, 默认为0 <br /> -XX:CMSMaxAbortablePrecleanTime :CMS可取消并发预处理阶段取消条件-->最长执行时间, 默认为5000毫秒 <br /> -XX:CMSScheduleRemarkEdenPenetration :CMS可取消并发预处理阶段取消条件-->Eden区的内存使用率大于此配置后取消, 默认值为50 <br /> -XX:+UseCMSCompactAtFullCollection :在进行Full GC之前进行一次内存整理, 默认开启 <br /> -XX:CMSFullGCBeforeCompaction=N :当执行过N此无碎片整理Full GC后,下次Full GC之前进行一次内存整理, 默认为0,表示每次都进内存整理 <br /> -XX:+CMSScavengeBeforeRemark :强制在CMS最终/重标记阶段前进行一次Minor GC, 防止可中断预清理一直没有等到年轻代Minor GC而导致年轻代对象太多而导致最终标记时间过长,导致停顿时间过长 <br /> -XX:+CMSPermGenSweepingEnabled :开启CMS对永久代(元空间)的垃圾收集, 默认不开启 <br />-XX: +CMSClassUnloadingEnabled :与-XX: +CMSPermGenSweepingEnabled 配合使用,收集永久代时卸载不用的类<br /> G1l垃圾收集器 <br /> -XX:G1HeapRegionSize=8 :设置G1垃圾收集器Region大小,取值范围应为1MB ~ 32MB,且应为2的N次幂。<br /> -XX:G1NewSizePercent :新生代最小值, 默认值5% <br /> -XX:G1MaxNewSizePercent :新生代最大值, 默认值60% <br /> -XX:ParallelGCThreads :STW期间,并行GC线程数<br /> -XX:ConcGCThreads=n :并发标记期间,GC线程数<br /> -XX:InitiatingHeapOccupancyPercent :设置触发标记周期的 Java 堆占用率阈值。默认值是45%。这里的java堆占比指的是nonyoungcapacitybytes,包括old+humongous<br /> -XX:G1HeapWastePercent :G1停止回收的最小内存,默认是堆的5%,就是说不必要每次回收就把所有的垃圾的处理完,可遗留少量的下次处理,这样也降低了单次GC消耗的时间<br /> -XX:+GCTimeRatio :计算花在Java应用线程上和花在GC线程上时间比率,默认是9,跟新生代内存的分配比例一样。 参数的主要目的是让用户可以控制花在应用上的时间,G1的计算公式是100/(1+GCTimeRatio)。 如果参数设置为9,则最多花10%的时间在GC上面,Parallel GC默认值是99,表示1%的时间被用在GC上面,这是因为Parallel GC贯穿整个GC,而G1则根据Region来进行划分,不需要全局性扫描整个内存<br /> -XX:G1ReserverPercent :G1为分配担保预留的空间比例, 默认10% ,也就是老年代会预留10%的空间来给新生代对象晋升,如果经常由于新生代对象晋升失败导致FullGC,可以适当调大此参数(调大此参数同时意味着老年代可使用的空间减少)
<a name="DvDjB"></a>
-XX:+-HeapDumpOnOutOfMemoryError :当OOMError产生时,自动Dump堆内存<br /> -XX:HeapDumpPath :与HeapDumpOnOutOfMemoryError搭配使用,指定内存溢出时Dump文件的目录, 默认为启动Java程序的工作目录下 <br /> -XX:OnError :发生致命错误时执行的脚本<br /> -XX:OnOutOfMemoryError :抛出OOMError错误是执行的脚本<br /> -XX:ErrorFile=fileName :致命错误的日志文件名,绝对路径或者相对路径<br /> -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1506 :开启远程调试<br /><br />
<a name="YJpQl"></a>
<a name="FxWab"></a>
-XX:+DoEscapeAnalysis :开启逃逸分析<br /> -XX:+EliminateAllocations :开启标量替换<br /> -XX:+EliminateLocks :开启同步消除<br />相关文章见: 编译优化技术 <br />
参考资料 :
性能测试三十六:内存溢出和jvm常见参数
堆内存溢出:
此种溢出,加内存只能缓解问题,不能根除问题,需优化代码
堆内存中存在大量对象,这些对象都有被引用,当所有对象占用空间达到堆内存的最大值,就会出现内存溢出OutOfMemory:Java heap space
永久代溢出
如果发生,则是在初始化的时候,空间太小,解决办法,扩大空间
类的一些信息,如类名、访问修饰符、字段描述、方法描述等,所占空间大于永久代最大值,就会出现OutOfMemoryError:PermGen space
内存溢出的检测方法:pid=1730
Jdk/bin目录下有很多检测工具
图形界面:
Jconsole
Jvisualvm
命令行工具:
Jstat –gcutil pid 1000 100 (只需要看O,如果达到100%,并且长期处于100%,则代表老年代内存不足)
pid:进程号、1000:1秒钟获取一次、100一共获取100次
E:eden区
O:老年代
P:永久代
YGC:新生代的GC次数
YGCT:当前统计的YGC一共花费的时间(毫秒)
FGC:fullGC老年代的GC次数
FGCT:当前统计的FGC一共花费的时间(毫秒)
GCT:YGC+FGC
Jmap –histo pid | head -20
把当前JVM里面的所有对象打印出来,排序,head:头部,head -20 前20行
Jmap –heap pid(列出当前进程的堆的数据,一般用来看当前配置)
在jvisualvm上面也可以看到JVM参数
FullGC频率:单次FullGC时间<200ms
Jvm常见参数
-Xms2048m,初始堆大小,建议<物理内存的1/4,默认值为物理内存的1/64
-Xmx2048m,最大堆大小,建议与-Xms保持一致,默认值为物理内存的1/4
-Xmn512m,新生代大小,建议不超过堆内存的1/2
-Xss256k,线程年轻代堆栈大小,建议256k
-XX:PermSize=256m,永久代初始值,默认值为物理内存的1/64
-XX:MaxPermSize=256m,永久代最大值,默认值为物理内存的1/4
-XX:SurvivorRatio=8:年轻带中Eden区和Survivor区的比例,默认为8:1:1,即Eden(8),From Space(1),ToSpace(1)
-XX:+UseConcMarkSweepGC:开启CMS垃圾回收器
看一下内存溢出的情况
先配置一下tomcat里面JVM的参数:vi /home/server/tomcat-PerfTeach01/bin/catalina.sh
由于ip变了,改一下host里面的ip
启动tomcat
能访问,代表启动成功:http://localhost:8080/PerfTeach/MemoryLeak?userId=123&password=abc&waitTime=3
jmeter5个并发永远跑
TPS
响应时间
cpu
jstat -gcutil 1730 1000 1000
jvisualvm
看一下tomcat日志的后200行
有内存溢出的报错
看当前JVM里面的所有对象,找com开头的,业务代码,再找非java开头的
可以看出org.apache可能有问题,com.lee是业务代码,一定有问题
直接告诉开发,让开发去解决
jvisualvm也可以生成快照,一开始出现内存泄漏的时候就点堆Dump在服务器下生成快照,下载后再用 jvisualvm打开, jvisualvm_文件_装入_文件类型选“线程 Dump”
内存泄漏的本质:老年代空间里面东西放满了,又不能被回收
程序一旦出现内存泄漏,就算停止压测也不能解决,只能重启
内存泄露会出现的现象
1,tps出现大幅波动,并慢慢降低,甚至降为0,响应时间随之波动,慢慢升高
2,通过jstat命令看到,Jvm中Old区不断增加,FullGC非常频繁,对应的FullGC消耗的时间也不断增加
3,通过jconsole/jvisualvm可以看到,堆内存曲线不断上升,接近上限时,变成一条直线
4,日志报错java.lang.OutOfMemoryError: Java heap space
内存泄露定位
1,通过jmap命令:jmap -histo pid | head -20,查看当前堆内存中实例数和占用内存最多的前20个对象
2,通过jvisualvm,进行远程堆dump,然后把dump文件下载下来,用jvisualvm打开进行分析,可以看到更直观的jvm中对象的信息
监控内存泄露问题的场景
1,在试压阶段,或任意场景都可以考虑通过jvisualvm和jstat监控jvm的情况
2,在稳定性场景中,一定要关注Jvm内存使用的情况,在长时间的压测下,最容易看出内存泄露的问题
以上是关于常见的JVM参数的主要内容,如果未能解决你的问题,请参考以下文章
JVM的内存结构,Eden和Survivor比例;JVM中一次完整的GC流程,对象如何晋升到老年代,说说你知道的几种主要的JVM参数;CMS 常见参数解析;.你知道哪几种垃圾收集器,各自的优缺点(代码