jmap执行失败如何获取heapdump详解

 更新时间:2023年04月16日 15:58:31   作者:扣钉日记  
这篇文章主要为大家介绍了jmap执行失败如何获取heapdump详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

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

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


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

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

  • 如果jvm进程id是8255,jmap会先创建一个/tmp/.java_pid8255文件,然后发送SIGQUIT信号给jvm。
  • jvm收到信号后启动AttachListener线程,以UNIX domain socket的形式监听/tmp/.java_pid8255文件,以接收命令。
  • jmap也以UNIX domain socket的形式连接上/tmp/.java_pid8255文件,并发送dumpheap命令给jvm,这个过程中jvm会检查命令发送方用户的euid/egid是否与自己一致。
  • 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占位符解释

占位符解释
%ppid
%uuid
%ggid
%ssignal number
%tUNIX time of dump
%hhostname
%eexecutable 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的资料请关注脚本之家其它相关文章!

相关文章

  • mybatis中返回主键一直为1的问题

    mybatis中返回主键一直为1的问题

    这篇文章主要介绍了mybatis中返回主键一直为1的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 使用filter实现url级别内存缓存示例

    使用filter实现url级别内存缓存示例

    这篇文章主要介绍了使用filter实现url级别内存缓存示例,只需要一个静态类,在filter中调用,也可以全部写到filt里面。可以根据查询参数分别缓存,需要的朋友可以参考下
    2014-03-03
  • Java多线程Queue、BlockingQueue和使用BlockingQueue实现生产消费者模型方法解析

    Java多线程Queue、BlockingQueue和使用BlockingQueue实现生产消费者模型方法解析

    这篇文章主要介绍了Java多线程Queue、BlockingQueue和使用BlockingQueue实现生产消费者模型方法解析,涉及queue,BlockingQueue等有关内容,具有一定参考价值,需要的朋友可以参考。
    2017-11-11
  • Hibernate使用hbm.xml配置映射关系解析

    Hibernate使用hbm.xml配置映射关系解析

    这篇文章主要介绍了Hibernate使用hbm.xml配置映射关系解析,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • SpringBoot实现嵌入式 Servlet容器

    SpringBoot实现嵌入式 Servlet容器

    传统的Spring MVC工程部署时需要将WAR文件放置在servlet容器的文档目录内,而Spring Boot工程使用嵌入式servlet容器省去了这一步骤,本文就来设置一下相关配置,感兴趣的可以了解一下
    2023-12-12
  • SpringBoot中@Value获取值和@ConfigurationProperties获取值用法及比较

    SpringBoot中@Value获取值和@ConfigurationProperties获取值用法及比较

    在Spring Boot中,@Value注解是一个非常有用的特性,它允许我们将外部的配置注入到我们的Bean中,@ConfigurationProperties用于将配置文件中的属性绑定到 Java Bean 上,本文介绍了@Value获取值和@ConfigurationProperties获取值用法及比较,需要的朋友可以参考下
    2024-08-08
  • 五个很实用的IDEA使用技巧分享

    五个很实用的IDEA使用技巧分享

    IntelliJ IDEA 是一款优秀的 Java 集成开发环境,它提供了许多强大的功能和快捷键,可以帮助开发者提高编码效率和质量,本文就在为你介绍博主常用的五个IntelliJ IDEA使用技巧,希望能够给你带来一些工作效率上的提升
    2023-10-10
  • 浅谈Java多进程程序的运行模式

    浅谈Java多进程程序的运行模式

    这篇文章主要介绍了浅谈Java多进程程序的运行模式,包括对进程阻塞问题的讨论等,需要的朋友可以参考下
    2015-11-11
  • java基于netty NIO的简单聊天室的实现

    java基于netty NIO的简单聊天室的实现

    这篇文章主要介绍了java基于netty NIO的简单聊天室的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • eclipse修改jvm参数调优方法(2种)

    eclipse修改jvm参数调优方法(2种)

    本篇文章主要介绍了eclipse修改jvm参数调优方法(2种),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02

最新评论