JVM调优实战

一、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 → 定位问题代码

6、分析堆栈,修复死循环、正则回溯、并发问题等

相关推荐
__土块__1 天前
大厂后端一面模拟:从线程安全到分布式缓存的连环追问
jvm·redis·mysql·spring·java面试·concurrenthashmap·大厂后端
fly spider1 天前
一文概括 JVM 核心内容
jvm
brahmsjiang1 天前
Java类加载机制解析:从JVM启动到双亲委派,再到Android的特殊实现
android·java·jvm
cch89181 天前
C++、Python与汇编语言终极对比
java·开发语言·jvm
zshs0001 天前
从 HashMap 到基因法:同一套位运算思想,如何从 JVM 走到分布式数据库
jvm·数据库·分布式
彧翎Pro2 天前
基于 RO1 noetic 配置 robosense Helios 32(速腾) & xsense mti 300
前端·jvm
minji...2 天前
Linux 线程同步与互斥(二) 线程同步,条件变量,pthread_cond_init/wait/signal/broadcast
linux·运维·开发语言·jvm·数据结构·c++
woai33642 天前
JVM学习-基础篇-常见引用
jvm·学习
それども2 天前
理解JVM参数 Xss 线程的栈大小
jvm
玛卡巴卡ldf2 天前
【Springboot6】内存泄漏OOM、VisualVM、Arthas、Prometheus Grafana监控、垃圾回收
java·jvm·springboot