使用jmap(1.5)从java核心转储中提取信息

Sam*_*uel 9 java gdb coredump jdk1.5 jmap

长话短说,一些同事正在运行一个非常古老的设置(x86_64中的oc4j jdk1.5.6),其中一个应用程序恰好是关键任务.他们最近尝试部署新版本的应用程序,但是一旦他们执行java进程就会抛出核心转储并死掉.

问题是,核心转储看起来很好,gdb可以打开它们,但jmap和其他工具拒绝处理它们:

# /usr/java/jdk1.5.0_06/bin/jmap /usr/java/jdk1.5.0_06/bin/java core
Attaching to core core from executable /usr/java/jdk1.5.0_06/bin/java, please wait...
Error attaching to core file: Can't attach to the core file
Run Code Online (Sandbox Code Playgroud)

更新的版本抛出异常:

# jdk1.6.0_45/bin/jmap /usr/java/jdk1.5.0_06/bin/java core
Attaching to core core from executable /usr/java/jdk1.5.0_06/bin/java, please wait...
Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at sun.tools.jmap.JMap.runTool(JMap.java:179)
        at sun.tools.jmap.JMap.main(JMap.java:110)
Caused by: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versions are 20.45-b01. Target VM is 1.5.0_06-b05
        at sun.jvm.hotspot.runtime.VM.checkVMVersion(VM.java:224)
        at sun.jvm.hotspot.runtime.VM.<init>(VM.java:287)
        at sun.jvm.hotspot.runtime.VM.initialize(VM.java:357)
        at sun.jvm.hotspot.bugspot.BugSpotAgent.setupVM(BugSpotAgent.java:594)
        at sun.jvm.hotspot.bugspot.BugSpotAgent.go(BugSpotAgent.java:494)
        at sun.jvm.hotspot.bugspot.BugSpotAgent.attach(BugSpotAgent.java:348)
        at sun.jvm.hotspot.tools.Tool.start(Tool.java:169)
        at sun.jvm.hotspot.tools.PMap.main(PMap.java:67)
        ... 6 more
Run Code Online (Sandbox Code Playgroud)

gdb提供的信息很少,没有符号:

Reading symbols from /usr/java/jdk1.5.0_06/bin/java...(no debugging symbols found)...done.

[New Thread 9841]
[New Thread 31442]
[New Thread 31441]
...
Core was generated by `/usr/java/jdk1.5.0_06/bin/java -server -XX:+UseConcMarkSweepGC -XX:MaxHeapFreeR'.
Program terminated with signal 6, Aborted.
#0  0x0000003bbf030285 in ?? ()
(gdb) bt
#0  0x0000003bbf030285 in ?? ()
#1  0x0000003bbf031d30 in ?? ()
#2  0x0000000000000000 in ?? ()
Run Code Online (Sandbox Code Playgroud)

我从核心收集的唯一有价值的信息是大多数线程被阻止(我远不是一个gdb大师):

  35 Thread 10093  0x0000003bbfc0b1c0 in pthread_cond_timedwait@@GLIBC_2.3.2 ()
   from /lib64/libpthread.so.0
  34 Thread 10097  0x0000003bbfc0b1c0 in pthread_cond_timedwait@@GLIBC_2.3.2 ()
   from /lib64/libpthread.so.0
  33 Thread 10099  0x0000003bbfc0b1c0 in pthread_cond_timedwait@@GLIBC_2.3.2 ()
   from /lib64/libpthread.so.0
Run Code Online (Sandbox Code Playgroud)

此外,我不知道它是否真的相关.该应用程序几乎总是负载很重,我的赌注是已经有一些锁定争用,但由于这是另一个团队应用程序,我对它的了解非常浅.

我想这是一个很长的镜头,但我们可以做些什么来获得java线程转储或类似的东西?Sun是否曾经提供jdk的debuginfo,因为我认为openddk现在可以使用它?

提前致谢.

更新:另一个团队已经解决了这个问题,但没有从核心转储中获取信息,只是通过在测试系统中成功复制问题后的反复试验.我仍然对这件事感兴趣:如何调试jmap无法处理的古老java核心转储,它可能是未来有价值的信息,但似乎似乎没有解决该问题的方法.可能JVM内存已损坏,这就是jmap无法处理它的原因.

tom*_*kab 5

您可以在启动应用程序时添加以下JVM选项,这将允许您在发生致命JVM错误时运行您指定的任何命令:

-XX:OnError="<cmd args>"
Run Code Online (Sandbox Code Playgroud)

例如,您可以运行一个命令(或脚本)来执行某些操作,例如获取堆或线程转储.


Sky*_*ker 3

Jmap 和其他 JVM 实用程序对版本极其敏感。从您的错误来看,不言自明的是,希望在您的情况下不使用相同的 jvm。

\n\n

Java VisualVM可以直接加载核心转储。但您必须使用创建 core 文件的同一个 jvm。

\n\n

资源链接:

\n\n

/sf/answers/698704891/

\n\n

建议#1:

\n\n

kjkoster 在本教程中给出了解决方案。

\n\n
\n

需要使用JVM自带的jmap。从您的错误消息中,我了解到您使用的 jmap 版本与 JVM 的版本不同。

\n\n

请检查您的计算机上安装了哪些 JVM,并确保运行 jmap 时使用正确的版本。

\n\n

为了解决这些问题,我从不依赖路径。相反,我将 JAVA_HOME 设置为 JVM 使用的 JAVA_HOME,然后调用 JVM 和 jmap,如下所示:

\n\n

代码:

\n\n
$ JAVA_HOME=/usr/local/jdk1.6.0\n$ export JAVA_HOME\n$ ${JAVA_HOME}/bin/java ...\n\n...\n\n$ ${JAVA_HOME}/bin/jmap ...\n
Run Code Online (Sandbox Code Playgroud)\n\n

希望这可以帮助。

\n
\n\n
\n\n

建议#2:

\n\n

这是Chamilad一步步给出的完整解决方案。希望它能澄清您的根本原因和解决过程。

\n\n

几乎每个 Java 开发人员都知道jmap 和 jstack 工具JDK附带的它们提供了提取正在运行的 JVM 实例的堆和线程信息的功能。简单的。

\n\n

如果\xe2\x80\x99s 正在运行的 JVM 产生了死锁,并且您想在进程运行时获取线程转储怎么办?你进去并运行以下命令。

\n\n
jstack pid >> thread_dump.txt\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果系统不\xe2\x80\x99不知道jstack是什么。你并不惊慌,但你的脑后有一种轻微的感觉,告诉你这个周五你不会早退。

\n\n

所发生的情况是运行的 JVM 基于 JRE 而不是 JDK。JRE 是一个最小的运行时,它不包含 JDK 所包含的监控和分析工具。

\n\n

那么我们有什么选择呢?

\n\n
    \n
  1. 停止该过程。下载 JDK,在 JDK 之上再次启动该进程,并希望死锁再次发生。没有。
  2. \n
  3. 在笔记本电脑上启动 JVisualVM,并希望该进程已启用 JMX。没有。
  4. \n
  5. 工具包来救援!
  6. \n
\n\n

jstack 等功能在压缩<JDK_HOME>/lib包内的tools.jar 文件中实现。我们可以用它来调用JStack并获取正在运行的进程的线程转储。

\n\n

因此,我们继续下载并解压 JDK,然后运行以下命令。

\n\n
java -classpath <JDK_HOME>/lib/tools.jar sun.tools.jstack.JStack <pid> >> thread_dump.txt\n
Run Code Online (Sandbox Code Playgroud)\n\n

..并遇到以下错误。

\n\n
Exception in thread "main" java.lang.UnsatisfiedLinkError: no attach in java.library.path\n        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)\n        at java.lang.Runtime.loadLibrary0(Runtime.java:870)\n        at java.lang.System.loadLibrary(System.java:1122)\n        at sun.tools.attach.LinuxVirtualMachine.<clinit>(LinuxVirtualMachine.java:342)\n        at sun.tools.attach.LinuxAttachProvider.attachVirtualMachine(LinuxAttachProvider.java:63)\n        at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:208)\n        at sun.tools.jstack.JStack.runThreadDump(JStack.java:163)\n        at sun.tools.jstack.JStack.main(JStack.java:116)\n
Run Code Online (Sandbox Code Playgroud)\n\n

该死的!又被宠坏了!

\n\n

我们如何解决这个问题?上述错误是由于进程无法\xe2\x80\x99找到libattach.soJStack. 设置以下环境变量将帮助 JVM 找到libattach.so文件。

\n\n
export LD_LIBRARY_PATH=<JDK_HOME>/jre/lib/amd64/\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在让\xe2\x80\x99s再次运行JStack,这次有结果了!

\n\n
java -classpath <JDK_HOME>/lib/tools.jar sun.tools.jstack.JStack <pid> >> thread_dump.txt\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在我们有了线程转储,我们继续讨论堆转储。我们通常使用的工具是 jmap,但 JRE 上也没有该工具。所以呢?我们可以使用 JDK\xe2\x80\x99s bin 目录中的二进制文件,对吗?正确的?

\n\n
root@snowflake1 latest]# <JDK_HOME>/bin/jmap -heap <pid>\nAttaching to process ID <pid>, please wait\xe2\x80\xa6\nError attaching to process: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versions are 25.102-b14. Target VM is 25.91-b14\nsun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versions are 25.102-b14. Target VM is 25.91-b14\n at sun.jvm.hotspot.HotSpotAgent.setupVM(HotSpotAgent.java:435)\n at sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:305)\n at sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:140)\n at sun.jvm.hotspot.tools.Tool.start(Tool.java:185)\n at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)\n at sun.jvm.hotspot.tools.HeapSummary.main(HeapSummary.java:49)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at sun.tools.jmap.JMap.runTool(JMap.java:201)\n at sun.tools.jmap.JMap.main(JMap.java:130)\nCaused by: sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versions are 25.102-b14. Target VM is 25.91-b14\n at sun.jvm.hotspot.runtime.VM.checkVMVersion(VM.java:227)\n at sun.jvm.hotspot.runtime.VM.<init>(VM.java:294)\n at sun.jvm.hotspot.runtime.VM.initialize(VM.java:370)\n at sun.jvm.hotspot.HotSpotAgent.setupVM(HotSpotAgent.java:431)\n \xe2\x80\xa6 11 more\n
Run Code Online (Sandbox Code Playgroud)\n\n

没有!除非您将 JDK 版本与JRE 所在的确切版本相匹配相匹配,否则您会遇到上述问题(这是不言自明的)。因此,我们下载了我们的进程正在运行的 JRE 的 JDK,并再次运行 jmap。

\n\n
<JDK_HOME>/bin/jmap -dump:file=heap_dump.hprof <pid>\n
Run Code Online (Sandbox Code Playgroud)\n\n

资源链接:

\n\n
    \n
  1. 从正在运行的基于 JRE 的 JVM 中提取内存和线程转储
  2. \n
\n