admin管理员组

文章数量:1530517

2024年5月20日发(作者:)

java程序运行时,有时会产生javacore及heapdump文件, java程序在遇到致命问题时,

就会产生这两个文件,有时产生时,java应用不会死掉,还能继续运行,有时则java进程会

死掉,即java进程 被杀死。为了能够保留java应用发生致命错误前的java的运行状态,jvm

在死掉前产生两个文件,分别为javacore及heapdump文件。

javacore文件主要保存的是java应用各线程在某一时刻的运行的位置,即执行到哪一个类的

哪一个方法哪一个行上。javacore是一个文 本文件,打开后可以看到每一个线程的执行栈,

以stacktrace的方式显示。通过对javacore的分析可以得到应用是否“卡”在某一点上,即

在某 一点运行的时间太长,如数据库查询,长期得不到响应,最终导致系统崩溃。

heapdump文件是一个二进制文件,它保存了某一时刻jvm堆中对象情况,这种文件需要相

应的工具进行分析,笔者用得较多的是heap analyzer这个工具。这个文件最重要的作用就

是分析系统是否存在内存溢出的情况,通过heapanalyzer可以很简单地分析出溢出的位置。

这两个文件也可以手工的方式生成,经常我们会遇到系统变慢或无响应的情况,这个时候就

以采用手工的方式生成javacore及heapdump文 件,通过对这两个文件的分析,查出原因

进而解决问题,在unix/linux上,产生这两个文件的方法是首先,ps -ef|grep java 找出java

进程id ,然后再执行kill -3 进程号 的操作,等文件生成后再做一次同样的操作,再产生一

组文件,两组文件在分析javacore时特别有效,困为它可以看出在先后两个时间点上,线程

执行的位 置,如果发现先后两组数据中同一线程都执行在同一位置,则说明此处可能有问

题,因为程序运行是极快的,如果两次均在某一点上,说明这一点耗时是很大的。。

1. Java DUMP分析

Java dump 文件的格式和内容

Java dump 通常是文本格式(.txt),因此可以通过一般的文本编辑器进行阅读,阅读时需要注意段与行的格

式:

段格式

为了便于大家的分析,Java dump 的每一段的开头,都会用“-----”与上一段明显的区分开来。而每一段的

标题也会用“=====”作为标识,这样我们就能够很容易的找到每一段的开头和标题部分(如清单 1)。

清单 1. Java dump 段标题示例

NULL --------------------------------

0SECTION TITLE subcomponent dump routine

NULL ===============================

行格式

Java dump 文件中,每一行都包含一个标签,这个标签最多由 15 个字符组成(如清单2中所示)。其中

第一位数字代表信息的详细级别(0,1,2,3,4),级别越高代表信息越详细;接下来的两个字符是段

标题的缩写,比如,“CI” 代表 “Command-line interpreter”,“CL” 代表 “Class loader”,“LK” 代表 “Locking”,

“ST” 代表 “Storage”,“TI” 代表 “Title”,“XE” 代表 “Execution engine”等等;其余部分为信息的概述。

清单 2. Java dump 行标签和内容示例

1TISIGINFO Dump Event "uncaught" (00008000) Detail "java/lang/OutOfMemoryError"

received

不同版本的 JVM 所产生的 Java dump 的格式可能会稍有不同,但基本上都会包含以下几个方面的内容:

TITLE 信息块:描述 JAVA DUMP 产生的原因,时间以及文件的路径。

GPINFO信息块:GPF 信息。

ENVINFO 信息块:系统运行时的环境及 JVM 启动参数。

MEMINFO 信息块:内存的使用情况和垃圾回收记录。

LOCKS 信息块:用户监视器(Monitor)和系统监视器(Monitor)。

THREADS信息块:所有 java 线程的状态信息和执行堆栈。

CLASSES信息块:类加载信息。

回页首

利用 Java Dump 进行 JVM 故障诊断

由于 Java dump 文件包含的内容比较广泛,因此 JVM 的很多问题都可以通过 java dump进行诊断。这

些问题主要包括线程阻塞,CPU 使用率过高,JVM Crash,堆内存不足,和类装载等问题。

诊断线程阻塞问题

线程阻塞是我们在 java 多线程编程中经常遇到的问题。由于对后端有限资源的争用以及过度同步等问题,

经常会发现 Java dump 中某个资源(锁对象)下有太多的线程处于等待状态,这时候我们通常需要从以

下三个方面去诊断这个问题:

这个锁存在的目的是什么?有没有可能去掉这个锁或者缩小这个锁保护的范围,从而减少线程等

待问题发生的几率。

有哪些线程需要用到这个锁,有没有可能改用其它更好的替代方案。

当前哪个线程正在持有这个锁,持有的时间是多长,有没有可能缩短持有的时间。

比线程阻塞更严重的是死锁问题,当两个以上的线程互相等待对方的锁,从而形成一个环的时候,就会发

生死锁。关于如何使用 Java dump 诊断死锁的问题,请参考 在 WebSphere Application Server V6.1 应

用程序中跟踪死锁 一文,该文对此问题做了较为详细的介绍。

诊断 JVM Crash 问题

JVM Crash 是我们所碰到的最棘手的问题之一,它对整个系统的影响是致命的,并且总是让人防不胜防。

导致 JVM 崩溃的原因有很多,通常都是一些底层的错误。比如 JVM 本身的 bug,错误的 JNI 调用,

第三方原生模块(比如数据库驱动程序)中的 bug 等。JVM崩溃的原因复杂,并且大多都难以重现,所

以诊断起来有一定的难度。

一般来说,JVM 崩溃的时候,系统一般会自动产生一个 Java dump 文件(JVM 默认的设置参数就会触

发)。这个 Java dump 会帮我们记录下 JVM 崩溃的原因,相关的信息会记录在 TITLE 信息块,GPINFO

信息块和 THREADS 信息块中。

TITLE 信息块:用于确认问题产生的原因,即是否是由于一些底层错误而导致 JVM Crash。

GPINFO 信息块:用于查看问题的详细信息和问题定位。

THREADS信息块:用于了解问题线程的运行情况。

下面我们通过一个具体的例子来介绍 JVM Crash 问题的诊断方法。TestJni 是一个简单的 Java 应用,

它通过 JNI 调用本地代码 中的 doSomeThing() 函数。

清单 3. 在 TestJni 类中调用 中的函数

本文标签: 问题文件线程信息系统