JVM-调优

堆空间的参数设置

-Xms:初始堆空间内存(默认为物理内存的1/64),建议设置成最大

-Xmx:最大堆空间内存(默认为物理内存的1/4)

-XX:NewRatio:新生代:老年代
-XX:NewRatio=2 2:8
-XX:SurvivorRatio:Eden:S0:S1
-XX:SurvivorRatio=8: 8:1:1

-Xmn:设置新生代的大小(初始和最大同一个)
-XX:PermSize 永久代初始值
-XX:MaxPermSize=n 永久代最大值

-verbose:class 在控制台打印类加载信息
-verbose:gc 在控制台打印垃圾回收日志

-XX:+PrintGC 打印GC日志,内容简单
-XX:+PrintGCDetails 打印GC日志,内容详细
-XX:+PrintGCDateStamps 在GC日志中添加时间戳

-Xloggc:filename 指定gc日志路径 -Xloggc:/data/jvm/gc.log

-XX:+UseSerialGC 年轻代设置串行收集器Serial

-XX:+UseParallelGC 年轻代设置并行收集器Parallel Scavenge

-XX:ParallelGCThreads=n 设置Parallel Scavenge收集时使用的CPU数。并行收集线程数。 -XX:ParallelGCThreads=4

-XX:MaxGCPauseMillis=n 设置Parallel Scavenge回收的最大时间(毫秒) -XX:MaxGCPauseMillis=100

-XX:GCTimeRatio=n 设置Parallel Scavenge垃圾回收时间占程序运行时间的百分比。公式为1/(1+n) -XX:GCTimeRatio=19

-XX:+UseParallelOldGC 设置老年代为并行收集器ParallelOld收集器
-XX:+UseConcMarkSweepGC 设置老年代并发收集器CMS

-XX:+CMSIncrementalMode 设置CMS收集器为增量模式,适用于单CPU情况。

-XX:MaxTenuringThreshold:设置新生代垃圾的最大年龄

-XX:+PrintGCDetails:输出详细的GC处理日志

日志信息

调优可以参考的数据有:
系统运行日志、堆栈错误信息、gc日志、线程快照、堆转储快照等

①系统运行日志:系统运行日志就是在程序代码中打印出的日志,描述了代码级别的系统运行轨迹(执行的方法、入参、返回值等),一般系统出现问题,系统运行日志是首先要查看的日志。

②堆栈错误信息:当系统出现异常后,可以根据堆栈信息初步定位问题所在,
比如根据“java.lang.OutOfMemoryError: Java heap space”可以判断是堆内存溢出;
根据“java.lang.StackOverflowError”可以判断是栈溢出;
根据“java.lang.OutOfMemoryError: PermGen space”可以判断是方法区溢出等。

③GC日志:程序启动时用 -XX:+PrintGCDetails 和 -Xloggc:/data/jvm/gc.log 可以在程序运行时把gc的详细过程记录下来,或者直接配置“-verbose:gc”参数把gc日志打印到控制台,通过记录的gc日志可以分析每块内存区域gc的频率、时间等,从而发现问题,进行有针对性的优化。

④线程快照:根据线程快照可以看到线程在某一时刻的状态,当系统中可能存在请求超时、死循环、死锁等情况是,可以根据线程快照来进一步确定问题。通过执行虚拟机自带的“jstack pid”命令,可以dump出当前进程中线程的快照信息

⑤堆转储快照:
程序启动时可以使用 “-XX:+HeapDumpOnOutOfMemory” 和 “-XX:HeapDumpPath,当程序发生内存溢出时,把当时的内存快照以文件形式进行转储(也可以直接用jmap命令转储程序运行时任意时刻的内存快照),事后对当时的内存使用情况进行分析。

JVM调优工具

jps(JVM process Status)

jps可以查看虚拟机启动的所有进程、执行主类的全名、JVM启动参数
比如当执行了JPSTest类中的main方法后(main方法持续执行),执行 jps -l可看到下面的JPSTest类的pid为31354,加上-v参数还可以看到JVM启动参数。

31354 com.danny.test.code.jvm.JPSTest

jstat(JVM Statistics Monitoring Tool)

jstat查看堆信息

jstat -gc pid 500 10 :每500毫秒打印一次Java堆状况
(各个区的容量、使用容量、gc时间等信息),打印10

jmap(Memory Map for Java)

jmap查看堆内存信息

jmap -histo pid:打印出当前堆中所有每个类的实例数量和内存占用,
 jmap -dump 可以转储堆内存快照到指定文件

jconsole

jconsole分析内存信息(各个区如Eden、Survivor、Old等内存变化情况)

JVM调优经验

新生代、老年代应该配置多大最合适呢?
答案是不一定,调优就是找答案的过程

建议如下:

-Xms和-Xmx的值设置成相等。

新生代尽量设置大一些,让对象在新生代多存活一段时间,每次Minor GC 都要尽可能多的收集垃圾对象,防止或延迟对象进入老年代的机会,以减少应用程序发生Full GC的频率。

写代码的建议

避免死循环

尽量避免长时间等待外部资源(数据库、网络、设备资源等)的情况

不要多层嵌套循环

防止递归爆栈

缩小对象的声明周期,比如能定义在方法中就不要定义在方法外面。

避免创建过大的对象及数组
过大的对象或数组在新生代没有足够空间容纳时会直接进入老年代,如果是短命的大对象,会提前出发Full GC。

避免同时加载大量数据
可以分批读取,用完尽快清空引用。

当集合中有对象的引用,这些对象使用完之后要尽快把集合中的引用清空,这些无用对象尽快回收避免进入老年代。

如果不能及时返回结果可以适当采用异步处理的方式等。

参考:
添加链接描述

猜你喜欢

转载自blog.csdn.net/qq_40337086/article/details/120762030