一、JVM调优参数在哪设置
1.var包部署在tomcat中设置
修改TOMCAT_HOME/bin/catlina.sh文件
JAVA_OPTS="-Xms512m -Xmx1024m"
2.jar包部署在启动参数设置
通常在linux系统下直接加参数启动springboot项目
bash
nohup java -Xms512m -Xmx1024m -jar xxx.jar --spring.profiles.active=prod &
nohup:用于在系统后台不挂断地运行命令,退出终端不会影响程序的运行
参数&:让命令在后台执行,终端退出后命令仍旧执行。
二、JVM调优的参数有哪些?
对于JVM调优,主要就是调整年轻代、老年代、元空间的内存空间大小及舒勇的垃圾回收器类型。
具体设置参见javase的文档
下面是常见的设置:
- 设置堆空间大小
- 虚拟机栈的设置
- 年轻代中Eden区和两个Survivor区的大小比例设置
- 年轻代晋升老年代阈值
- 设置垃圾回收收集器
1.设置堆空间大小
设置堆的初始大小和最大大小,为了防止垃圾收集器在初始大小、最大大小之间收缩堆而产生额外的时间,通常把最大、初始大小设置为相同的值
bash
-Xms:设置堆的初始化大小
-Xmx:设置堆的最大大小
不指定单位默认是字节
指定了单位,按照指定的单位
-Xms:1024
-Xms:1024k
-Xms:1024m
-Xms:1g
1.1堆空间设置多少合适?
最大大小的默认值是物理内存的1/4,初始大小是物理内存的1/64
堆太小,可能会频繁的导致年轻代和老年代的垃圾回收,会产生stw,暂停用户线程
堆内存大肯定是好的,存在风险,加入发生了fullgc,它会扫描整个堆空间,暂停用户线程的时间长
设置参考推荐:尽量大,也要考察一下当前计算机其他程序的内存使用情况。
2.虚拟机栈的设置
每个线程默认会开启1M的内存,用于存放栈帧、调用参数、局部变量等,但一般256k就够用。通常减少每个线程的堆栈,可以产生更多的线程,但这实际上还手限于操作系统。
bash
-Xss 对每个线程stack大小的调整,-Xss128k
3.年轻代中Eden区和两个Survivor区的大小比例
设置年轻代中Eden区和两个Survivor区的大小比例。该值如果不设置,则默认比例为8:1:1.通过增大Eden区的大小,来减少YGC发生的次数,但有时我们发现,虽然次数减少了,但Eden区满的时候,由于占用的空间较大,导致释放缓慢,此时STW的时间较长,因此需要按照程序情况区调优。
bash
-XXSurvivorRatio=8 表示年轻贷中的分配比率:survivor:eden=2:8
4.年轻代晋升老年代的阈值
bash
-XXMaxTenuringThreshold=threshold
- 默认为15
- 取值范围0-15
5.设置垃圾回收收集器
通过增大吞吐量提高系统性能,可以通过设置并行垃圾回收收集器。
bash
-XX:+UseParallelGC
-XX:+UseParallelOldGC
-XX:+UseG1GC
三、JVM调优工具
命令工具
- jps 进程状态信息
- jstack 查看java进程内线程的堆栈信息
- jmap 查看堆转信息
- jhat 堆转储快照分析工具
- jstat JVM统计检测工具
可视化工具
jconsole 用于对JVM的内存,线程,类的监控
VisualVM 能够监控线程,内存情况
1.命令
jps
进程状态信息

jstack
查看java进程内线程的堆栈信息
jstack [option] <pid>
jmap
用于生成堆转内存快照、内存使用情况
bash
jmap -heap pid 显示java堆的信息
jmap -dump:format=b,file=heap.hprof pid
format=b 表示以hprof二进制格式转储java堆的内存
file=<filename> 用于指定快照dump文件的文件名。
例如:
jmap -dump:format=b,file=/Users/luyulong/jvmdump/123.hprof 6787

它是一个进程或系统在某一给定的时间的快照。比如在进程崩溃时,甚至是任何时候,我们都可以通过工具将系统或某进程的内存备份出来供调试分析用。dump文件中包含了程序运行的模块信息、线程信息、堆栈调用信息、异常信息等数据,方便系统技术人员进行错误排查。
jstat
是JVM统计监测工具。可以用来显示垃圾回收信息、类加载信息、新生代统计信息等。
1、总结垃圾回收统计 jstat -gcutil pid

2、垃圾回收统计 jstat -gc pid

2.可视化工具
1.jconsole
用于对JVM的内存,线程,类的监控,是一个基于jmx的GUI性能监控工具
打开方式:java安装目录bin目录下,直接启动jconsole.exe就行


2.VisualVM
能够监控线程,内存情况,查看方法的CPU时间和内存中的对象,已被GC的对象,反向查看分配的堆栈
打开方式:java安装目录bin目录下,直接启动jvisualvm.exe就行

三、java内存泄露的排查思路


- 1、获取堆内存快照dump
- 2、VisualVM去分析dump文件
- 3、通过查看堆信息的情况,定位内存溢出问题
1、获取堆内存快照dump
1)通过jmap指定打印他的内存快照dump
(dump文件是进程的内存镜像,可以把程序的执行状态通过调试器保存到dump文件中)
使用jmap命令获取运行中程序的dump文件
bash
jmap -dump:format=b,file=heap.hprof pid
2)使用vm参数获取dump文件
有的情况是内存溢出之后程序则会直接中断,而jmap智能打印在运行中的程序,所以建议通过参数的方式生成dump文件
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/home/app/dumps/

2、通过工具,VisualVM去分析dump文件
VisualVM可以加载离线的dump文件
文件-》装入-》选择dump文件即可查看堆快照信息

3、通过查看堆信息的情况,可以大概定位内存溢出是哪行代码出了问题

4、找到对应的代码,通过阅读上下文的情况,进行修复即可
四、CPU飙高,排查方案与思路
1、使用top命令查看占用cpu的情况


通过top命令查看后,可以查看是哪一个进程占用CPU较高,上图所示的进程为:8483
2、通过ps命令,查看是哪个线程占用的cpu过高
bash
ps H -eo pid,tid,%cpu |grep 2266
3、线程号的十进制转换成16进制(使用jstack pid 中显示出来的是16进制的)
使用如下命令
bash
printf "%x\n" 线程id
4、根据得到的16进制数,去jstack结果中查找对应的线程。
jstack <PID> > jstack.log
5、定位问题代码
grep -A 30 "nid=0x1a2b" jstack.log → 定位问题代码