一、JVM调优的参数在哪里设置
项目开发过程中有以下两种部署项目的方式:
- 项目部署在tomcat中,是一个war包;
- 项目部署在SpringBoot中,是一个jar包。
(1)war包
catalina文件在Linux系统下的tomcat是以sh结尾,在windows系统下则是以bat结尾。
"Xms512m"指的是堆的初始化大小是512兆,"Xmx1024m"指的是堆的最大大小是1024兆。
(2)jar包
加上这两个参数的作用:假设我们使用最简单的java -jar方式来启动一个单体项目,并且加上这两个项目,就可以让它在后台运行。
(3)总结
二、JVM调优的参数有哪些
(1)设置堆空间大小
(2)虚拟机栈的设置
因为每个线程都会分配一个虚拟机栈,若将线程的默认内存增大,那么就会减少总共能生成的线程的数量;若将线程的默认内存减小,而某一个方法中的参数过多,就有可能会出现栈内存溢出。所以一般建议设置256k或512k即可。
(3)Eden区与两个Survivor区的大小比例
“-XXSurvivorRatio=8"代表Eden区占了总年轻代中的八份空间;“survivor:eden"代表两个Survivor区共用两份空间,Eden区占了八份空间。
当设置”-XXSurvivorRatio=3”,幸存者区参数不变时,"survivor:eden"就等于2:3。
(4)年轻代晋升老年代的阈值
这个"阈值"指的是年轻代当中某对象被挪动的次数,当挪动次数超过这个阈值,该对象就会从年轻代晋升到老年代。
(5)设置垃圾回收器
因为我们当前使用的是JDK8,在JDK8默认的垃圾回收器是Parallel GC(并行GC)。当然也可以使用G1垃圾回收器,只要使用"-XX:+Use"参数来指定想要使用的垃圾回收器即可。
(6)总结
三、JVM调优的工具
(1)命令工具
- jps
jps
- jstack
jstack [option] <pid>
pid指的就是刚刚使用jps命令查询到的进程id。
在控制台中就会展示出当前线程的详细信息。假如产生了死锁,就可以使用jstack来查看线程运行的情况。
3. jmap
//显示堆信息
jmap -heap pid
//生成指定进程的dump文件并指定保存的地址
jmap -dump:format=b,file=heap.hprof pid
jmap -heap pid
jmap -dump:format=b,file=heap.hprof pid
4. jstat
//总结垃圾回收统计
jstat -gcutil pid
//垃圾回收统计
jstat -gc pid
①总结垃圾回收统计
S0、S1、E、O、M、CCS下的数字代表他们当前在内存中使用的比例,YGC、YGCT、FGC、FGCT、GCT代表年轻代与老年代进行垃圾回收的次数或消耗时间。
②垃圾回收统计
用于查看垃圾回收的情况
(2)可视化工具
- jconsole
在该工具内就可以查看当前的内存使用情况了
- VisualVM
但是该工具目前仅有JDK8可以直接在bin目录下启动,高版本JDK必须到官网自行下载使用。
监控程序运行情况:
查看运行中的dump:
查看当前正在运行的线程的情况:
(3)总结
四、Java内存泄露的排查思路
(1)出现内存泄漏的区域
内存泄露指的是丢失了数据的地址,没法引用也没法删除。
可能会产生内存泄露的区域:运行时数据区中的三块内存-虚拟机栈、方法区、堆空间。
虚拟机栈发生内存泄漏的报错信息- StackOverFlowError ,指递归造成的问题;
方法区内存不足的报错信息- OutOfMemoryError:MetaSpace ,指动态加载的类太多导致元空间内存不足;
堆空间内存泄露的报错信息- OutOfMemoryError:java heap space ,是最常见的报错情况,也是我们需要最主要关注的,一般出现在一些大对象一直存活,一直没有被垃圾回收器回收的情况。
(2)服务器排查
而我们的项目通常是部署在服务器上的,且拆分成了很多的微服务,每个微服务也都是一个独立的项目,都有可能会出现内存溢出导致服务宕机,这时候要想进行内存排查就需要采用以下方式:
①获取快照dump文件
- 因为要想使用jmap命令就必须将项目启动起来,并根据其线程id来查询,但是当服务宕机时是无法获取到线程id的,此时也就不能使用jmap命令。
- 而使用vm参数则可以直接在命令中指定jvm虚拟机参数来指定需要查看的线程情况。
HeapDumpPath用于指定dump文件存储到的地址。
使用方法:
配置vm参数,并指定dump文件存储到的路径地址
运行程序,发现dump文件已经成功存储,且出现 OutOfMemoryError
生成文件
②使用VisualVM分析dump文件
③查看堆信息,找到报错原因
(3)总结
五、CPU飙高的排查方案及思路
什么是CPU飙高:我们的项目运行在服务器上且占用的CPU较高。
(1)CPU占用情况排查
在linux系统上打印该命令就能查看当前占用CPU的排行,可以看到占用最高的进程是一个java程序,进程id为2266。
也就是说当前某个java项目占用CPU太高了,我们的任务就是要找到该项目中哪一行代码导致的该问题,也就是进行代码排查。而代码都是在不同线程当中运行的,我们就需要找到对应的线程并定位该问题。
(2)排查操作
- 获取当前2266进程中的所有线程
可以看到2276线程占用的CPU最高,也就是该线程导致的CPU占用率过高的问题
- 使用jstack命令查看2266进程中的全部线程信息
- 定位到指定线程的信息
因为前面查询到的2276线程id是一个十进制数,而在jstack命令中查询出的日志中的线程id都是十六进制数,所以需要先对线程id进行转换。
再在jstack查询出的日志中定位到该8e4线程的信息,也就可以找到是哪行代码出现问题
- 定位java代码
可以发现是代码中的死循环的问题