服务器部署方式为tomcat中运行war包的方式, 有一次重新部署时候发现报异常堆栈溢出了.
想要定位到某个war包中通过学习整理出此篇文章以作记录笔记.
不要看到free
很少就很慌或者used
很高, 就以为内存爆了. 其实不是, 是因为Linux内存管理技术 -- 虚拟内存
参考2: tomcat内存占用过高_jvm疯狂吞占内存,罪魁祸首是谁?
如果存储数据或缓存的分区过大, 可以给分区扩容或清理缓存的方法.
/dev/vda[数字]过大情况下可参考一下连接:
通过jps
指令查看系统中运行的项目
如果还有tomcat运行包, 会多一条[pid] Bootstrap
数据
(服务器测试时没有jar包的名称, 可能Bootstrap名称也会不同)
生成线程堆栈转储文件(war和jar都是使用java执行的, 都是查看进程id)
使用jmap -dump:format=b,file=wanfile.dump 21445
导出堆栈文件, 并且下载到本地. jmap生成的堆转储文件包含了Java堆中的所有对象的详细信息, 所以会大一点, 对比jcmd和jstack.
相关的指令还有jcmd
: jcmd <进程ID> GC.heap_dump <文件路径>
jcmd是JDK中的一个命令行工具,用于与Java进程进行交互并执行各种操作。它提供了一系列的命令,可以用于监控、诊断和调试Java应用程序。以下是jcmd的一些常用功能:
VM相关操作:jcmd可以执行与Java虚拟机(JVM)相关的操作,如生成堆转储文件、强制执行垃圾收集、打印系统属性等。例如,您可以使用jcmd <进程ID> GC.run
命令来强制执行垃圾收集操作。
线程相关操作:jcmd可以查看和管理Java进程中的线程。您可以使用jcmd <进程ID> Thread.print
命令来打印线程的详细信息,包括线程ID、状态、堆栈跟踪等。还可以使用jcmd <进程ID> Thread.dump
命令生成线程的堆栈转储文件。
类相关操作:jcmd可以执行与Java类相关的操作,如打印加载的类信息、触发类卸载等。例如,您可以使用jcmd <进程ID> VM.class_stats
命令来打印加载的类的统计信息。
JMX相关操作:jcmd可以与Java管理扩展(JMX)进行交互,执行与MBeans相关的操作。您可以使用jcmd <进程ID> ManagementAgent.start
命令启动JMX代理,以便远程管理和监控Java进程。
JVM统计信息:jcmd可以获取Java进程的各种统计信息,如线程、类加载、垃圾收集、编译器等的统计数据。您可以使用jcmd <进程ID> VM.native_memory
命令来查看本地内存使用情况。
其余的请参考相关的JDK文档或运行jcmd -help
命令来获取帮助信息。
另外还可以使用jstack生成线程快照, 功能与jcmd类似(jstack较旧, jcmd新一点): jstack 21445 > 21445.log
也可以打印在命令行, 或者使用 | grep 'at com.'
来过滤. 另外介绍一个网站: FastThread可以分析这些堆栈信息.
参考: tomcat服务器cpu占用率居高不下
参考: 线上问题排查命令
参考: Tomcat进程占用CPU过高怎么办?
jvisualvm.exe
打开, 与java.exe
和javac.exe
都在同目录%JSAVA_HOME/bin%
下点击显示系统属性
, 可以查看到当前的jar包运行的参数, 包括当前jar包的名称.
之后我也将Bootstrap
也下载了下来
类
: 可以查看堆栈中的类信息, 主要查看自己定义的类的实例数和ArrayList
是否过高
注: java11包括java11之后的版本不再提供jvisualvm.exe
, 有需要的话可以在VisualVM: Download 下载.
参考2: jvisualvm.exe使用介绍
如果常用jdk(系统变量path中配置的)是java8的话, 由于此工具要求jdk版本是java11+, 所以需要手动配置java11, 在MemoryAnalyzer.exe
同目录下的MemoryAnalyzer.ini
配置文件中最前面添加-vm path
:
-vm
C:\Program\Java\java-11\bin\javaw.exe
-startup
plugins/org.eclipse.equinox.launcher_1.6.400.v20210924-0641.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.2.400.v20211117-0650
-vmargs
-Xmx1024m
参考1: 官网下载地址
参考3: Memory Analyzer基本使用
参考4: 一文让你理解什么是shallow heap及retained heap
tomcat中的各个war的运行情况暂时无法分开查看
目标tomcat
的bin
目录下的catalina.sh
文件内添加以下内容并重启tomcat
使用jar运行的话, 也是添加以下参数
# 1.之前是写到一行, 但是启动有问题, 后面拆开多行成功
# 2.hostname填写ip或者域名
# 3.port使用的是与tomcat或docker相同的端口(尝试使用不同的未能成功, 于参考4中发现)
# 4.authenticate代表是否需要鉴权
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote=true"
CATALINA_OPTS="$CATALINA_OPTS -Djava.rmi.server.hostname=[ip or servername]"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.port=80"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
打开软件visualvm
, 右键打开Add Remote Host...
输入hostname
, 目标服务器的ip或域名, 点击OK
右键新添加的远程主机, 点击Add JMX Connection...
填写上接口, 同服务器配置中的port
如果配置上jmxremote.authenticate=true
, 需要填写上配置的用户名和密码
勾选上不需要SSL连接, 同配置中的jmxremote.ssl=false
点击OK
后其下会出现下图所示
双击上图箭头所指位置, 右侧窗口中可看到具体内容
visualvm
功能可在官网上的Features
和Documentation
进行查阅.
JDK Mission Control(jmc)
jconsole
参考1: jvisualvm.exe使用
参考2: VisualVM详解
参考3: jvisualvm 监控 tomcat 实例(qbit)
参考4: Has anyone ever got a remote JMX JConsole to work?
参考5: jvisualvm之jmx远程连接