java配置OOM时保存堆转储文件

简介: java配置OOM时保存堆转储文件

当Java程序发生OOM(OutOfMemoryError)时,如果想要自动转储堆内存以便分析,可以在启动JVM时配置下列参数:

-XX:+HeapDumpOnOutOfMemoryError

这个参数可以让JVM在抛出OOM异常时自动生成heap dump文件。

-XX:HeapDumpPath=./java_pid<pid>.hprof

指定生成的heap dump文件的存放路径和文件名,这里使用了pid作为文件名的一部分,可以将不同时间的堆转储区分开。

-XX:OnOutOfMemoryError=<命令>

当OOM发生时,可以执行指定的命令,例如用于通知或执行脚本。

所以典型的带有堆转储的启动参数可以是:

java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./java_pid<pid>.hprof -Xmx512m ...

这样就可以在OOM发生时自动获取堆转储文件。分析这个文件可以定位内存泄漏或其他内存问题。

hprof文件自定义

一开始我想要使用生成时间作为heap dump文件名的一部分,配置方法如下:

-XX:HeapDumpPath=./java_oom-%t.hprof

经过实验,果然不行,原因是 HeapDumpPath 中如果使用 %t 或者 %%t 作为时间戳占位符,在运行时实际上并不能被 JVM 解析替换。

经过询问claude,得到两个解决方案,但是我还没实验,等验证过再来更新,先记录上

1.使用时间戳+计数器的方式生成唯一堆转储文件名

主要思路是:

  1. 启动Java程序时,使用一个循环脚本wrap着它
  2. 这个循环脚本中会不停地监听Java进程的PID
  3. 当检测到OOM产生时,脚本中会做两件事:
    3.1 动态设置HeapDumpPath参数,即堆转储文件的路径,文件名使用时间戳+计数器确保唯一性
    3.2 向Java进程发送kill -3 {pid} 信号,触发堆转储

这里的关键就是一旦监听到OOM事件,动态设置一个唯一的文件名,然后通知Java进程进行堆转储。

具体示例脚本代码:

# oom_wrap.sh
COUNT=1
while true; do
   PID=$(pgrep -f java) 
   if [ $? -ne 0 ]; then
     echo "Java process died"
     exit 1
   fi
   FILE=heapdump-${DATE}+${COUNT}.hprof  
   gsignal -s 3 -p heapdumpfile $FILE $PID 
   let COUNT=COUNT+1 
   sleep 10
done

启动Java程序时,用这个脚本包着:

./oom_wrap.sh java -Xmx128m ...

这里提到的gsignal是用来向进程发送信号的工具。

每次转储后复制文件到新的唯一文件名中

可以使用 Linux 的 crontab 定时任务来完成。

例如配置一个每小时执行的脚本:/path/to/heapdump-copy.sh

# heapdump-copy.sh
DUMP_DIR=/path/to/dumps
cd $DUMP_DIR
if [ -n "$(ls -1t java_oom_*.hprof | head -n 1)" ]; then
    NEWEST_DUMP=$(ls -1t java_oom_*.hprof | head -n 1)
    NEW_FILENAME=java_oom_$(date +%Y%m%d%H%M).hprof
    cp $NEWEST_DUMP $NEW_FILENAME
    echo "Copied new heap dump file $NEW_FILENAME"
fi

脚本逻辑:

  1. 检查 dumps 目录下最新的 java 堆转储文件
  2. 如果存在的话,复制到带时间戳的新文件名中

然后在 crontab 中增加定时任务:

0 * * * * /path/to/heapdump-copy.sh

这样就可以每小时检查并复制最新生成的 OOM 堆转储文件了。

crontab 定时任务还可以结合日志记录、监控报警使用,让自动化堆转储复制更加可靠。

目录
相关文章
|
29天前
|
Java
有关Java发送邮件信息(支持附件、html文件模板发送)
有关Java发送邮件信息(支持附件、html文件模板发送)
30 1
|
30天前
|
Java 数据库连接 数据库
hibernate正向生成数据库表以及配置——TestStu.java
hibernate正向生成数据库表以及配置——TestStu.java
16 1
|
30天前
|
Java 数据库连接 数据库
hibernate正向生成数据库表以及配置——Teacher.java
hibernate正向生成数据库表以及配置——Teacher.java
11 0
|
30天前
|
Java 数据库连接 数据库
hibernate正向生成数据库表以及配置——Student.java
hibernate正向生成数据库表以及配置——Student.java
10 0
|
1月前
|
Java
java中替换文件内容
java中替换文件内容
14 1
|
1月前
|
Java API
Java中文件与输入输出
Java中文件与输入输出
|
1月前
|
Java
java实现遍历树形菜单方法——映射文件VoteTree.hbm.xml
java实现遍历树形菜单方法——映射文件VoteTree.hbm.xml
9 0
|
1月前
|
Java
java程序导出堆文件
java程序导出堆文件
|
3天前
|
Java 关系型数据库 MySQL
Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
【4月更文挑战第12天】Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
28 3
|
1天前
|
Java
Java配置环境
Java配置环境
7 0
Java配置环境