[转帖]jmap执行失败了,怎么获取heapdump?

jmap,执行,失败,怎么,获取,heapdump · 浏览次数 : 0

小编点评

**jmap内存导出失败的原因** 由于您使用的是容器中的jvm进程, jmap可能无法访问到容器内的内存。这是因为容器中的jvm进程可能使用不同的用户身份和内存布局,导致jmap无法读取到正确的内存区域。 **解决方案** 您可以尝试以下解决方案来解决问题: 1. **使用内核级coredump机制**:内核级coredump机制可以自动将容器中的内存保存到core文件中,而内核会保证该文件是完整和完整的。您可以使用 `ulimit` 命令设置内核级coredump的内存限制,例如: ```bash ulimit -c unlimited ``` 2. **设置jmap的memmap参数**:`memmap` 参数可以指定要读取的内存区域的地址和大小。您可以尝试使用以下参数来解决问题: ```bash jmap -F -m 1024 -v /path/to/core.hprof ``` 其中,`1024` 代表要读取的内存区域的字节数,`-m` 参数表示使用内存映射,`-v` 参数表示启用 verbose 模式。 3. **使用其他工具**:如果您无法访问容器中的core文件,您可以使用其他内存分析工具,例如: * MAT(Memory Analyzer Tool) * JVisualVM * JMC(Java Memory Analyzer) **注意** * 使用内核级coredump机制可能会影响容器的性能,因为它需要额外的内核资源。 * 使用其他内存分析工具也可能需要使用特定的工具或软件,您可以根据您的需求选择合适的工具。

正文

https://www.jianshu.com/p/f4bfd169b4ca

 

 

在之前的OOM问题复盘中,我们添加了jmap脚本来自动dump内存现场,方便排查OOM问题。

但当我反复模拟OOM场景测试时,发现jmap有时可以dump成功,有时会报错,如下:

 

 

经过网上一顿搜索,发现两种原因可能导致这个问题,一是执行jmap用户与jvm进程用户不一致,二是/tmp/.java_pidXXX文件被删除,但经过检查,这都不是我们jmap失败的原因。

经过了解,jmap导出内存的原理,大致如下:

 

 

  1. 如果jvm进程id是8255,jmap会先创建一个/tmp/.java_pid8255文件,然后发送SIGQUIT信号给jvm。
  2. jvm收到信号后启动AttachListener线程,以UNIX domain socket的形式监听/tmp/.java_pid8255文件,以接收命令。
  3. jmap也以UNIX domain socket的形式连接上/tmp/.java_pid8255文件,并发送dumpheap命令给jvm,这个过程中jvm会检查命令发送方用户的euid/egid是否与自己一致。
  4. AttachListener线程收到dumpheap命令后,等到JVM进入Safepoint后,执行HeapDumper操作以导出heap.hprof文件。

可以看出,当jvm已经卡死,或有长时间的GC正在Safepoint中执行,都会导致jmap长时间读不到命令的响应而超时失败!

使用jmap -F

当给jmap添加-F参数时,jmap会使用Linux的ptrace机制来导出堆内存,ptrace是Linux平台的一种调试机制,像strace、gdb都是基于它开发的,它使得调试进程(jmap)可以直接读取被调试进程(jvm)的原生内存,然后jmap再根据jvm的内存布局规范,将原生内存转换为hprof格式。

但在实际执行时,会发现jmap -F执行得非常慢,可能要几个小时,这是因为ptrace每次只能读一个字的内存,而我们的堆有10G,因此jmap -F对于我们几乎无法使用。

注:这里说的原生程序,指的是类似于C/C++这种直接编译出来、不需要依赖语言虚拟机的程序,而原生内存,指的是通过malloc或mmap等直接申请出来的内存。

使用gcore

有过Linux下原生程序调试经验的,应该会知道gcore这个实用工具,它可用来生成程序原生内存的core文件,然后jstack、jmap等都可以读取此类文件,如下:

# 生成core文件,8787是进程号
$ gcore -o core 8787
Saved corefile core.8787
[Inferior 1 (process 8787) detached]

$ ll -lh core.8787
-rw-r--r-- 1 work work 5.8G 2023-04-16 11:40:00 core.8787

# 从core文件中读取线程栈
$ jstack `which java` core.8787

# 将core文件转换为hprof文件,很慢,建议摘流量后执行
$ jmap -dump:format=b,file=heap.hprof `which java` core.8787

但是当我使用jmap转换core文件时,我发现我本机测试时可以成功,但在测试服务器上却一直报错,如下:

 

 

我网上找了好久,都没找到报此错误的原因...

但我发现gcore执行时,是有一些警告信息的,如下:

 

看起来可能是gcore导出的core文件不全,联想到jvm部署在容器中,怀疑是有某些权限限制,导致部分程序内存导出失败了。

 

使用Linux内核的coredump机制

除了gcore可以导原生内存,其实Linux内核也有自动的coredump机制,即进程在收到某些信号后,会自动触发内核的coredump机制,内核会负责将进程的原生内存保存为core文件,而内核一般是最高权限运行的,所以它生成的core文件应该是完整的。

先开启coredump机制,如下:

# 检查是否开启,输出unlimited表示core文件不受限制,即完全开启
$ ulimit -c

# 临时开启coredump
$ ulimit -c unlimited

# 永久开启
$ echo "ulimit -c unlimited" >> /etc/profile

然后,配置一下coredump文件保存位置,如下:

# 查看当前配置
$ cat /proc/sys/kernel/core_pattern
/home/core/core.%e.%p.%t

# 配置coredump文件保存位置,并使其生效
$ vi /etc/sysctl.conf
kernel.core_pattern=/home/core/core.%e.%p.%t
$ sysctl –p /etc/sysctl.conf

core_pattern占位符解释

占位符解释
%p pid
%u uid
%g gid
%s signal number
%t UNIX time of dump
%h hostname
%e executable filename

注:如果没有权限修改core_pattern路径,可考虑使用软链接ln -s做路径跳转,当然,还需要保证coredump路径有写入权限。

配置ok后,可通过kill发送信号来触发内核coredump,可触发coredump的常见信号如下:

  • SIGQUIT 数值2 从键盘输入Ctrl+'\'可以产生此信号
  • SIGILL 数值4 非法指令
  • SIGABRT 数值6 abort调用
  • SIGSEGV 数值11 非法内存访问
  • SIGTRAP 数值5 调试程序时使用的断点

我选择了SIGABRT信号,即kill -6,经过验证,可生成core文件,而且core文件也能被jmap转换为hprof文件。

有了hprof文件,就可以愉快地使用MAT、JVisualVM、JMC等工具进行内存分析啦😁

与[转帖]jmap执行失败了,怎么获取heapdump?相似的内容:

[转帖]jmap执行失败了,怎么获取heapdump?

https://www.jianshu.com/p/f4bfd169b4ca 在之前的OOM问题复盘中,我们添加了jmap脚本来自动dump内存现场,方便排查OOM问题。 但当我反复模拟OOM场景测试时,发现jmap有时可以dump成功,有时会报错,如下: 经过网上一顿搜索,发现两种原因可能导致这个

[转帖]java获取到heapdump文件后,如何快速分析?

https://www.jianshu.com/p/aaf56385766d 简介 在之前的OOM问题复盘之后,本周,又一Java服务出现了内存问题,这次问题不严重,只会触发堆内存占用高报警,没有触发OOM,但好在之前的复盘中总结了dump脚本,会在堆占用高时自动执行jstack与jmap,使得我们

[转帖]JVM监控和诊断工具

目录 jps jstat jmap jinfo jstack 总结 作者:@dwtfukgv本文为作者原创,转载请注明出处:https://www.cnblogs.com/dwtfukgv/p/15126148.html JVM监控和诊断工具 jps 它将打印所有正在运行的Java进程的相关信息。

[转帖]JVM调优常用命令(jstat、jmap、jstack)

原文:https://www.cnblogs.com/ityouknow/p/5714703.html 一、jstat jstat(JVM statistics Monitoring)是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。 命令

[转帖]查看堆内对象的工具:jmap

文章目录 用途命令格式示例一,no option二,heap三,histo[:live]四,clstats五,finalizerinfo六,dump: 用途 jmap 可以查看堆内对象的信息,生成 java 程序的 dump 文件,甚至可以查看 ClassLoader 的

[转帖]java并发-一些系统分析工具

https://segmentfault.com/a/1190000041541631 内存分析 java内存分析一般采用Java jmap dump下系统内存文件,使用 jmat 进行分析。 线程分析 线程栈一般通过 jstack 得到。 cpu分析 火焰图arthas 火焰图做为cpu调试的神器

[转帖]JVM性能调优监控工具

原文 https://www.cnblogs.com/haiyang1985/p/7654654.html 摘要: JDK自己提供了不少方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps、jstack、jmap、jhat、jstat、hprof等小巧的工具,本

[转帖] JVM诊断命令jcmd介绍

https://www.cnblogs.com/codelogs/p/16535451.html 简介# 从JDK7开始,jdk提供了一个方便扩展的诊断命令jcmd,用来取代之前比较分散的jdk基础命令,如jps、jstack、jmap、jinfo等,并且jdk添加新的诊断功能,也会通过jcmd提供

[转帖] JVM诊断命令jcmd介绍

https://www.cnblogs.com/codelogs/p/16535451.html 简介# 从JDK7开始,jdk提供了一个方便扩展的诊断命令jcmd,用来取代之前比较分散的jdk基础命令,如jps、jstack、jmap、jinfo等,并且jdk添加新的诊断功能,也会通过jcmd提供

[转帖]Cat导致内存不足原因分析

背景 线上几亿的数据在回刷的时候容器服务会出现OOM而重启,导致任务中断 内存泄露分析 jmap -histo pid 找出了有几十亿的java.lang.StackTraceElement对象,找不到被谁引用了 jmap -dump:format=b,file=heapdump.hprof pid