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、分析堆栈,修复死循环、正则回溯、并发问题等

相关推荐
u0109272716 小时前
持续集成/持续部署(CI/CD) for Python
jvm·数据库·python
m0_706653238 小时前
Python生成器(Generator)与Yield关键字:惰性求值之美
jvm·数据库·python
qq_423233909 小时前
实战:用Python开发一个简单的区块链
jvm·数据库·python
编程(变成)小辣鸡10 小时前
JVM、JRE和JDK 的关系
java·开发语言·jvm
hello 早上好10 小时前
02_JVM 架构模型中“栈式”与“寄存器式”指令集架构
jvm·架构
青槿吖11 小时前
【趣味图解】线程同步与通讯:从抢奶茶看透synchronized、ReentrantLock和wait/notify
java·开发语言·jvm·算法
难得的我们11 小时前
如何为开源Python项目做贡献?
jvm·数据库·python
焦糖玛奇朵婷11 小时前
就医陪诊小程序|从软件开发视角看实用度✨
java·大数据·jvm·算法·小程序
岳轩子11 小时前
jvm学习 引入 第一晚
jvm·学习