使用gcore生成核心转储文件后,将其转换为hprof文件格式时,出现错误信息。

19
我们最近遇到了一个JVM崩溃的情况,留下了由gcore命令产生的核心转储文件。我们想查看文件内容并找出导致崩溃的原因。
使用jmap命令,您可以将核心转储文件转换为hprof文件格式,然后可以使用VisualVM和许多其他工具进行分析。我尝试过这样做,并收到了错误消息。这是我运行的命令(在发生崩溃的同一台机器上,使用相同的JVM):
jmap -dump:format=b,file=dump.hprof /usr/java/jdk1.6.0_16/bin/java core.dump.2878

整个响应如下:
> Attaching to core core.dump.8483 from executable /usr/java/jdk1.6.0_16/bin/java, please wait...
> Error attaching to core file: Can't attach to the core file

这不是一个非常有用的错误信息。我曾经想过可能是权限问题,但是以引起核心转储的JVM所使用的相同用户来运行命令时,我收到了相同的信息。我还怀疑核心文件是否已损坏,因此决定使用gdb查看是否可以打开核心文件并查看其中的内容。以下是所得到的:

> gdb
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-37.el5_7.1)
GPLv3+许可证:GNU GPL第3版或更高版本
这是自由软件:您可以更改和重新分发它。
在法律允许的范围内,没有保修。键入“show copying”和“show warranty”以获取详细信息。
此GDB配置为“x86_64-redhat-linux-gnu”。
有关错误报告说明,请参见:
<http://www.gnu.org/software/gdb/bugs/>。
(gdb) core-file core.dump.8483
[新线程2889]
[新线程2893]
[新线程2894]
[新线程2895]
[新线程2896]
[新线程2904]
[新线程2915]
[新线程2916]
[新线程2917]
[新线程2921]
[新线程2922]
[新线程3175]
[新线程3239]
[新线程3252]
[新线程3258]
[新线程3260]
[新线程3356]
[新线程3509]
[新线程3510]
[新线程3514]
[新线程3523]
[新线程3541]
[新线程3542]
[新线程3543]
[新线程4022]
[新线程4057]
[新线程4058]
[新线程4077]
[新线程4078]
[新线程4079]
[新线程4080]
[新线程6128]
[新线程6140]
[新线程6162]
[新线程6376]
[新线程6389]
[新线程6408]
[新线程6422]
[新线程6429]
[新线程6451]
[新线程6497]
[新线程6513]
[新线程6514]
[新线程6516]
[新线程6517]
[新线程6532]
[新线程6533]
[新线程6665]
[新线程6675]
[新线程6676]
[新线程6687]
[新线程6689]
[新线程6692]
[新线程6706]
[新线程6707]
[新线程6735]
[新线程6736]
[新线程7033]
[新线程7034]
[新线程7056]
[新线程7077]
[新线程7079]
[新线程7080]
[新线程7082]
[新线程7089]
[新线程7090]
[新线程7091]
[新线程7092]
[新线程7103]
[新线程7105]
[新线程7107]
[新线程7108]
[新线程7116]
[新线程7229]
[新线程7308]
[新线程7493]
[新线程7505]
[新线程7510]
[新线程7511]
[新线程7517]
[新线程7523]
[新线程7604]
[新线程7617]
[新线程7618]
[新线程7619]
[新线程8676]
[新线程8693]
[新线程8700]
[新线程8851]
[新线程8860]
[新线程8887]
[新线程9007]
[新线程9118]
[新线程9119]
[新线程9120]
[新线程9413]
[新线程9427]
[新线程9495]
[新线程9508]
[新线程9519]
[新线程9535]
[新线程9536]
[新线程9537]
[新线程9554]
[新线程9556]
[新线程9659]
[新线程9660]
[新线程9663]
[新线程9664]
[新线程9665]
[新线程9666]
[新线程9667]
[新线程9668]
[新线程9669]
[新线程9670]
[新线程9671]
[新线程9678]
[新线程9870]
[新线程9953]
[新线程9998]
[新
在那一刻,我放弃了,因为我对和如何使用它来诊断这种问题一无所知。我甚至不太理解最后一个命令到底做了什么。值得注意的一件事是,在输出中正好有134个“New Thread”行,如果每个线程都代表JVM中新生成的一个线程,那么这可能就是JVM死亡的原因。
所以我的问题实际上有三个方面 -
1)您是否知道为什么命令会出现错误消息?
2)您是否知道输出的含义?
3)您是否知道如何使用进一步诊断此问题?

你说你正在使用相同的用户运行,但是你指定的JVM版本是否完全相同?可能性不大... - daveb
是的,它是。该路径是通过运行 ps -ef 并查看应用程序使用的 JVM 得出的。 - Jon
3个回答

5
顺便说一下,jvisualvm可以直接加载核心转储文件。但是您必须使用创建核心文件的相同jvm。

我在VisualVM的任何地方都没有看到加载核心转储文件的选项。我看到了加载“.apps”、“ .tdump”、“.hprof”、“.nps”和“ .npss”的选项。但这些选项中没有一个能使核心转储文件在“选择文件”对话框中可见。 - Jon
2
@Jon 前往文件 -> 添加 VM 核心转储。更多信息请参见此处:http://docs.oracle.com/javase/6/docs/technotes/guides/visualvm/coredumps.html - daveb
2
好的,阅读了文档,看起来那应该可以工作,但是它在我的Windows桌面上不可用(只有*nix),而产生核心转储的目标服务器没有运行X窗口系统。 - Jon
在Windows上运行X服务器并将其指向Linux显示器非常容易:http://stackoverflow.com/questions/40453/what-is-a-good-and-free-x-server-for-windows。VisualVM可以在远程Linux上运行,但会以本地窗口的形式出现。 - Vadzim
1
你需要使用相同的Java版本,所以如果你有一个Linux/Unix核心文件,当然不能用Windows jvisualvm打开它。安装一个带有Linux的虚拟机来获取GUI或使用jmap提取hprof文件。 - eckes

5

核心文件是否大于2GB?如果是,您可能遇到了JVM附带的libsaproc.so Linux版本的问题。

请再次运行您的命令,但像这样:

strace -o out.txt -f $yourOriginalCommand

接下来执行命令 'grep core.2878 out.txt' 并查找 open() 系统调用的错误。它返回了错误(E_XXXXX)还是文件句柄号码?


根据 du -h core.dump.2878 的输出,它的大小为1.8G。远程服务器上的发行版似乎没有可用的 strace 命令(Red Hat Linux)。 - Jon
Jon - 我不得不下载openjdk6源代码并使用大文件支持重新构建libsaproc.so以使用JDK工具。你接近2GB。如果你的核心文件大小(以字节为单位)大于2^31,则可能会遇到相同的问题。如果你有一个openjdk构建环境,请编辑openjdk-6-src-b22-28_feb_2011/hotspot/make/linux/makefiles/saproc.make,将-D_FILE_OFFSET_BITS=64包含在$(LIBSAPROC)部分中。然后LD_PRELOAD=your/libsaproc.so jmap ... - Heathkit7

5

这件事困扰了我很久,因为我有一个代表堆的核心文件需要分析,但我经常看到下面的异常信息:

sun.jvm.hotspot.debugger.NoSuchSymbolException: 在已知的库名称中(libjvm.so、libjvm_g.so、gamma_g)找不到符号“gHotSpotVMTypeEntryTypeNameOffset”

将源机器的jre复制到目标机器的完全相同的文件夹中,然后使用该java位置作为参数运行jmap对我有效。

因此,以下是其他人遇到这种情况时可以尝试的步骤:
1. 通过gdb连接到核心文件并确认正在运行的进程使用的java二进制文件的位置:

    gdb --core=</path/to/core-file>

2. 上述输出结果将以以下内容结尾:

[New Thread 22748]
**Core was generated by `/opt/blah/location/jre/bin/java -Xmx...'.**

3. 确保您将与之匹配的jre版本复制到/opt/blah/location/目录中。

  1. Then launch jmap as:

    /opt/jdk1.8.0_09/bin/jmap -heap /opt/blah/location/jre/bin/java /path/to/core-file
    

    This should connect to the core file successfully and print out heap statistics. If it does, then you have successfully read the core file

  2. From that point on, you can generate the hprof from the core file successfully using:

    /opt/jdk1.8.0_09/bin/jmap -dump:format=b,file=my-file.hprof /opt/blah/location/jre/bin/java /path/to/core-file
    

2
应该是:/opt/jdk1.8.0_09/bin/jmap -dump:format=b,file=my-file.hprof /opt/blah/location/jre/bin/java /path/to/core-file - vinay chilakamarri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接