- 浏览: 190022 次
- 性别:
- 来自: 上海
文章分类
最新评论
对于大型 java 应用程序来说,再精细的测试都难以堵住所有的漏洞,即便我们在测试阶段进行了大量卓有成效的工作,很多问题还是会在生产环境下暴露出来,并且很难在测试环境中进行重现。JVM 能够记录下问题发生时系统的运行状态并将其存储在转储(dump)文件中,从而为我们分析和诊断问题提供了重要的依据。常见的转储文件包括 Java Dump, Heap dump 和 System dump。这里我们主要介绍 Java dump 在 JVM 故障诊断中的应用。
Java dump,也叫做 Thread dump,是 JVM 故障诊断中最重要的转储文件之一。JVM 的许多问题都可以使用这个文件进行诊断,其中比较典型的包括线程阻塞,CPU 使用率过高,JVM Crash,堆内存不足,和类装载等问题。作为一款轻量级(与 Heap dump 和 System dump 相比)的转储文件,Java dump 的确是我们诊断 JVM 问题的首选。本文将系统的介绍使用 Java dump 进行 JVM 故障诊断的方法和技巧,希望能够为大家提供一些帮助。
jstack Dump 日志文件中的线程状态
dump 文件里,值得关注的线程状态有:
死锁,Deadlock(重点关注)
执行中,Runnable
等待资源,Waiting on condition(重点关注)
等待获取监视器,Waiting on monitor entry(重点关注)
暂停,Suspended
对象等待中,Object.wait() 或 TIMED_WAITING
阻塞,Blocked(重点关注)
停止,Parked
产生时间
Java程序运行时,有时会产生JavaCore及HeapDump文件,它一般发生于Java程序遇到致命问题的情况下。
有时致命问题发生后,Java应用不会死掉,还能继续运行;
但有时致命问题发生,Java进程会死掉;
为了能够保留Java应用发生致命错误前的运行状态,JVM在死掉前产生两个文件,分别为JavaCore及HeapDump文件(是需要在启动参数中配置的-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapdump,不配置不生成dump文件)。
一、标准的SUN/Oracle JVM
当内存溢出时生成heapdump文件配置如下
-Xloggc:${目录}/temp_gc.log (GC日志文件)
-XX:+HeapDumpOnOutOfMemoryError (内存溢出时生成heapdump文件)
-XX:HeapDumpPath=${目录} (heapdump文件存放位置)
如果要即时动态生成heapdump文件可以使用jmap命令,jdk6.0已取消了-XX:+HeapDumpOnCtrlBreak配置参数通过ctrl+break的方式。
jmap -dump:format=b,file=temp_heapdump.hprof <pid>
有何区别
JavaCore是关于CPU的,而HeapDump文件是关于内存的。
JavaCore文件主要保存的是Java应用各线程在某一时刻的运行的位置,即JVM执行到哪一个类、哪一个方法、哪一个行上。它是一个文本文件,打开后可以看到每一个线程的执行栈,以stack trace的显示。通过对JavaCore文件的分析可以得到应用是否“卡”在某一点上,即在某一点运行的时间太长,例如数据库查询,长期得不到响应,最终导致系统崩溃等情况。
HeapDump文件是一个二进制文件,它保存了某一时刻JVM堆中对象使用情况,这种文件需要相应的工具进行分析,如IBM Heap Analyzer这类工具。这类文件最重要的作用就是分析系统中是否存在内存溢出的情况。
怎么生成
这两个文件可以用手工的方式生成,当我们会遇到系统变慢或无响应的情况,这时就以采用手工的方式生成JavaCore及HeapDump文件。
在Unix/Linux上,产生这两个文件的方法如下:
# ps -ef | grep java
user 4616 4582 0 17:30 pts/0 00:00:00 grep java
root 5580 1 0 Oct27 ? 00:02:27 /usr/bin/java -server -XX:PermSize=64M -XX:MaxPermSize=128m -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=/usr/local/tomcat8090/conf/logging.properties -Djava.endorsed.dirs=/usr/local/tomcat8090/endorsed -classpath :/usr/local/tomcat8090/bin/bootstrap.jar -Dcatalina.base=/usr/local/tomcat8090 -Dcatalina.home=/usr/local/tomcat8090 -Djava.io.tmpdir=/usr/local/tomcat8090/temp org.apache.catalina.startup.Bootstrap start
# kill -3 5580 (目前已经不生成)
首先,找出Java进程id ,然后再执行‘kill -3 进程号’的操作,等文件生成后再做一次同样的操作,再产生一组文件。
如何分析
JavaCore文件
两组文件在分析JavaCore时特别有效,因为它可以看出在先后两个时间点上,线程执行的位置,如果发现先后两组数据中同一线程都执行在同一位置,则说明此处可能有问题,因为程序运行是极快的,如果两次均在某一点上,说明这一点耗时是很大的,通过对这两个文件进行分析,查出原因,进而解决问题。
JavaCore文件的头部有一个“Current Thread Details”标记,它记录了JavaCore产生时系统运行的线程id,使用线程id在文件中查找线程的详细信息,该信息中记载了线程运行哪个类的时候造成的JavaCore。
NULL ------------------------------------------------------------------------
0SECTION TITLE subcomponent dump routine
NULL ===============================
1TISIGINFOOUTOFMEMORY received
1TIDATETIME Date: 2011/12/07 at 15:59:42
1TIFILENAME Javacore filename:/usr/WebSphere/AppServer/profiles/WCSProdNode2/javacore19202086.1323298782.txt
NULL ------------------------------------------------------------------------
0SECTION XHPI subcomponent dump routine
NULL ==============================
1XHTIME Wed Dec 7 15:59:42 2011
1XHSIGRECV Unexpected signal -1 received at 0x0 in <unknown>. Processing terminated.
1XHFULLVERSION J2RE 1.4.2 IBM AIX build ca142ifx-20090918 (SR13 FP2)
NULL
1XHCURRENTTHD Current Thread Details
NULL ----------------------
2XHCURRSYSTHD "WebContainer : 5" sys_thread_t:0x45FB5328
3XHNATIVESTACK Native Stack
NULL ------------
3XHSTACKLINEERR unavailable - stack address not valid
:::
:::
0SECTION XM subcomponent dump routine
NULL ============================
NULL
1XMCURTHDINFO Current Thread Details
NULL ----------------------
3XMTHREADINFO "WebContainer : 5" (TID:0x70A8E260, sys_thread_t:0x45FB5328, state:R, native ID:0x5CC0) prio=5
4XESTACKTRACE at org.apache.taglibs.standard.tag.common.core.ImportSupport$ImportResponseWrapper.getString(Unknown Source)
4XESTACKTRACE at org.apache.taglibs.standard.tag.common.core.ImportSupport.acquireString(Unknown Source)
4XESTACKTRACE at org.apache.taglibs.standard.tag.common.core.ImportSupport.doEndTag(Unknown Source)
4XESTACKTRACE at com.ibm._jsp._part._jspx_meth_c_import_3(_part.java(Compiled Code))
4XESTACKTRACE at com.ibm._jsp._part._jspx_meth_c_otherwise_3(_part.java(Compiled Code))
4XESTACKTRACE at com.ibm._jsp._part._jspx_meth_c_choose_4(_part.java(Compiled Code))
4XESTACKTRACE at com.ibm._jsp._part._jspService(_part.java:3237)
这样结合当时的日志文件可以找到问题产生的原因。不过,这种方法只能找到不是内存溢出的错误,对于在core文件头就有java/lang/outMemoryException的错误还是不知道是执行到哪个类的时候出现。
HeapDump文件
HeapDump文件是指定时刻的Java堆栈的快照,是一种镜像文件。Heap Analyzer工具通过分析HeapDump文件,哪些对象占用了太多的堆栈空间,来发现导致内存泄露或者可能引起内存泄露的对象。
其中jmap是java自带的工具
查看整个JVM内存状态
jmap -heap [pid]
要注意的是在使用CMS GC 情况下,jmap -heap的执行有可能会导致JAVA 进程挂起
查看JVM堆中对象详细占用情况
jmap -histo [pid]
导出整个JVM 中内存信息
jmap -dump:format=b,file=文件名 [pid]
jhat是sun 1.6及以上版本中自带的一个用于分析JVM 堆DUMP 文件的工具,基于此工具可分析JVM HEAP 中对象的内存占用情况
jhat -J-Xmx1024M [file]
执行后等待console 中输入start HTTP server on port 7000 即可使用浏览器访问 IP:7000
eclipse Memory Analyzer
Eclipse 提供的一个用于分析JVM 堆Dump文件的插件。借助这个插件可查看对象的内存占用状况,引用关系,分析内存泄露等。
http://www.eclipse.org/mat/
[color=red]kill -3 [pid] (目前已经不生成)
在Linux 上找到Java所在的进程号,然后执行以上命令,线程的相关信息就输出到console
jstack
jstack 是sun JDK 自带的工具,通过该工具可以看到JVM 中线程的运行状况,包括锁等待,线程是否在运行
执行 jstack [pid] ,线程的所有堆栈信息
"http-8080-10" daemon prio=10 tid=x0a949bb60 nid=0x884 waiting for monitor entry [...]
"http-8080-10" 这个线程处于等待状态。 waiting for monitor entry 如果在连续几次输出线程堆栈信息都存在于同一个或多个线程上时,则说明系统中有锁竞争激烈,死锁,或锁饿死的想象。
“http-8080-11” daemon prio=10 tix=xxx nid=xxx in object.wait() [...]
java.lang.Thread.State:waiting (on object monitor)
该表示http-8080-11的线程处于对象的Wait 上,等待其他线程的唤醒,这也是线程池的常见用法。
“Low Memory Detector”daemon prio=10 tix=xx nid=xxx runnable [...] java.lang.Thread.State:runnable
表示“Low Memory Detector” 的线程处于Runable状态,等待获取CPU的使用权.
[/color]
了分析java应用的内存泄漏,使用thread dump往往解决不了问题。使用jstat【eg:jstat -gcutil pid 1000 5】工具查看运行的java应用的heap size,perm size ,survivor ratio等,当时你无法知道是什么对象把堆填满了。
什么是 Java heap dump
首先需要搞懂什么是java heap,java heap是分配给实例类和数组对象运行数据区,所有java线程在运行期间共享heap中的数据。Java heap dump相当于java应用在运行的时候在某个时间点上打了个快照(snapshot)。
触发 Java heap dump
有以下方法出发heap dump
使用$JAVA_HOME/bin/jmap -dump来触发,eg:jmap -dump:format=b,file=/home/longhao/heamdump.out
使用$JAVA_HOME/bin/jcosole中的MBean,到MBean>com.sun.management>HotSpotDiagnostic>操作>dumpHeap中,点击 dumpHeap按钮。生成的dump文件在java应用的根目录下面。
在应用启动时配置相关的参数 -XX:+HeapDumpOnOutOfMemoryError,当应用抛出OutOfMemoryError时生成dump文件。
使用hprof。启动虚拟机加入-Xrunhprof:head=site,会生成java.hprof.txt文件。该配置会导致jvm运行非常的慢,不适合生产环境。
分析 Java heap dump
1:使用IBM HeapAnalyzer
IBM HeapAnalyzer是一款免费的JVM内存堆的图形分析工具,它可以有效的列举堆的内存使用状况,帮助分析Java内存泄漏的原因。
下载解压后有一个ha413.jar,执行: java -Xmx512m -jar ha413.jar /home/longhao/heapdump.out
2:jhat
jhat(Java Head Analyse Tool )是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言OQL,分析相关的应用后,可以通过http://localhost:7000来访问分析结果。
示例: $JAVA_HOME/bin/jhat -J-Xmx512m /home/longhao/dump.out
3:Eclipse MemoryAnalyzer
Eclipse Memory Analyzer是一个快速并且功能强大的Java heap分析器,能够帮助你查找内存泄漏和减少内存消耗。在File>Acquire Heap Dump>configure>HPROF jmap dump provider设置一下分析应用的JDK,点击相关应用列表来生成heap dump并分析。
在socket,nio中的有些API中,申请的内存是直接想OS要的,在堆中分析内存是查看不到的,可以通过-XX:MaxDirectMemorySize=来设置应用向OS直接申请的最大内存数。
1.jmap –heap pid
查看内存
查看指定java进程内的所有对象情况,统计信息
得到运行java程序的内存分配的详细情况。例如实例个数,大小等
命名行格式
jmap [ option ] pid
jmap [ option ] executable core
jmap [ option ] [server-id@]remote-hostname-or-IP
-dump:[live,]format=b,file=<filename> 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件.
-finalizerinfo 打印正等候回收的对象的信息.
-heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.
-histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.
-permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来.
-F 强迫.在pid没有相应的时候使用-dump或者-histo参数. 在这个模式下,live子参数无效.
-h | -help 打印辅助信息
-J 传递参数给jmap启动的jvm.
[wls81@CNSH-stg4-080 ~]$ jmap -heap 1345
Attaching to process ID 1345, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.45-b01
using parallel threads in the new generation. –新生代采用并行线程处理方式
using thread-local object allocation.
Concurrent Mark-Sweep GC –同步并行垃圾回收
Heap Configuration:
MinHeapFreeRatio = 40 –最小堆使用比例,小于40增加
MaxHeapFreeRatio = 70 –最大堆可用比例,大于70缩小
MaxHeapSize = 2147483648 (2048.0MB) –最大堆空间大小
NewSize = 21757952 (20.75MB)-新生代初始值
MaxNewSize = 43581440 (41.5625MB)- 新生代最大值
OldSize = 65404928 (62.375MB)
NewRatio = 7 -新域与旧域之比,如-XX:NewRatio = 7就表示新域与旧域之比为1:7
SurvivorRatio = 8 -新域中Eden区与两个Survivor区的比值
PermSize = 21757952 (20.75MB)
MaxPermSize = 268435456 (256.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 39256064 (37.4375MB)
used = 10106616 (9.638420104980469MB)
free = 29149448 (27.79907989501953MB)
25.745362550866027% used
Eden Space:
capacity = 34930688 (33.3125MB)
used = 8710216 (8.306709289550781MB)
free = 26220472 (25.00579071044922MB)
24.935712689083022% used
From Space:
capacity = 4325376 (4.125MB)
used = 1396400 (1.3317108154296875MB)
free = 2928976 (2.7932891845703125MB)
32.28389855587121% used
To Space:
capacity = 4325376 (4.125MB)
used = 0 (0.0MB)
free = 4325376 (4.125MB)
0.0% used
concurrent mark-sweep generation: --OG大小和使用情况
capacity = 2103902208 (2006.4375MB)
used = 621060520 (592.2894668579102MB)
free = 1482841688 (1414.1480331420898MB)
29.519457588781616% used
Perm Generation:
capacity = 221929472 (211.6484375MB)
used = 141924728 (135.34996795654297MB)
free = 80004744 (76.29846954345703MB)
63.9503742882784% used
2.Jmap -dump:format=b,file=dumpFileName pid
dump命令
1.jstat -gc pid
Jstat 一般用来查看堆内存的实时情况
这是一个比较实用的一个命令,可以观察到classloader,compiler,gc相关信息。可以时时监控资源和性能
jstat -gc 22225 2000 20 没个2秒显示一次,一共显示20次
命令格式
-class:统计class loader行为信息
-compile:统计编译行为信息
-gc:统计jdk gc时heap信息
-gcutil:统计gc时,heap情况
-gccapacity:统计不同的generations(不知道怎么翻译好,包括新生区,老年区,permanent区)相应的heap容量情况
-gccause:统计gc的情况,(同-gcutil)和引起gc的事件
-gcnew:统计gc时,新生代的情况
-gcnewcapacity:统计gc时,新生代heap容量
-gcold:统计gc时,老年区的情况
-gcoldcapacity:统计gc时,老年区heap容量
-gcpermcapacity:统计gc时,permanent区heap容量
S0C:年轻代中第一个survivor(幸存区)的容量 (字节)
S1C:年轻代中第二个survivor(幸存区)的容量 (字节)
S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
EC:年轻代中Eden(伊甸园)的容量 (字节)
EU:年轻代中Eden(伊甸园)目前已使用空间 (字节)
OC:Old代的容量 (字节)
OU:Old代目前已使用空间 (字节)
PC:Perm(持久代)的容量 (字节)
PU:Perm(持久代)目前已使用空间 (字节)
YGC:从应用程序启动到采样时年轻代中gc次数
YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)
FGC:从应用程序启动到采样时old代(全gc)gc次数
FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT:从应用程序启动到采样时gc用的总时间(s)
2.jstat -gcutil pid
S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
E:年轻代中Eden(伊甸园)已使用的占当前容量百分比
O:old代已使用的占当前容量百分比
P:perm代已使用的占当前容量百分比
jstack –l pid
stack –l pid > 111.log 生成线程快照到文件中
虚拟机自带的一种堆栈跟踪工具,生成虚拟机当前的线程快照。查看没有响应的线程出现的原因。
-l 长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表.
jstack能得到运行java程序的java stack和native stack的信息。可以轻松得知当前线程的运行情况,注:这个和thread dump是同样的结果。但是thread dump是用kill -3 pid命令,还是服务器上面少用kill为妙
linux的kill -3指令可以帮我们输出当前进程中所有线程的状态,如哪些线程在运行,哪些在等待,因为什么等待,代码哪一行等待。
kill -3 会将信息输出至控制台,所以使用时,被kill -3的进程最好是nohup启动的。
kill -3并不会影响程序运行,不用担心他把程序杀死了。执行kill -3 后 目前已经失效,jdk不在生成dump文件
jstack除了在正常运行的系统能连接上去以外,在系统已经不能正常提供JMX服务了,但进程还活着的时候,也能连接上去。
使用jstack命令的帮助可以看到,该工具的功能也很强大:
主要分为两个功能:
a. 针对活着的进程做本地的或远程的线程dump;
b. 针对core文件做线程dump。
比如,下面就是一个针对进程做的线程dump:
jstack除了进程活着的时候可以做dump,如果进程crash了,那么系统应该会留下core文件,jstack工具依然能够对core文件做线程dump,
jstack java.core
iostat
查看IO相关信息
Java dump,也叫做 Thread dump,是 JVM 故障诊断中最重要的转储文件之一。JVM 的许多问题都可以使用这个文件进行诊断,其中比较典型的包括线程阻塞,CPU 使用率过高,JVM Crash,堆内存不足,和类装载等问题。作为一款轻量级(与 Heap dump 和 System dump 相比)的转储文件,Java dump 的确是我们诊断 JVM 问题的首选。本文将系统的介绍使用 Java dump 进行 JVM 故障诊断的方法和技巧,希望能够为大家提供一些帮助。
jstack Dump 日志文件中的线程状态
dump 文件里,值得关注的线程状态有:
死锁,Deadlock(重点关注)
执行中,Runnable
等待资源,Waiting on condition(重点关注)
等待获取监视器,Waiting on monitor entry(重点关注)
暂停,Suspended
对象等待中,Object.wait() 或 TIMED_WAITING
阻塞,Blocked(重点关注)
停止,Parked
产生时间
Java程序运行时,有时会产生JavaCore及HeapDump文件,它一般发生于Java程序遇到致命问题的情况下。
有时致命问题发生后,Java应用不会死掉,还能继续运行;
但有时致命问题发生,Java进程会死掉;
为了能够保留Java应用发生致命错误前的运行状态,JVM在死掉前产生两个文件,分别为JavaCore及HeapDump文件(是需要在启动参数中配置的-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapdump,不配置不生成dump文件)。
一、标准的SUN/Oracle JVM
当内存溢出时生成heapdump文件配置如下
-Xloggc:${目录}/temp_gc.log (GC日志文件)
-XX:+HeapDumpOnOutOfMemoryError (内存溢出时生成heapdump文件)
-XX:HeapDumpPath=${目录} (heapdump文件存放位置)
如果要即时动态生成heapdump文件可以使用jmap命令,jdk6.0已取消了-XX:+HeapDumpOnCtrlBreak配置参数通过ctrl+break的方式。
jmap -dump:format=b,file=temp_heapdump.hprof <pid>
有何区别
JavaCore是关于CPU的,而HeapDump文件是关于内存的。
JavaCore文件主要保存的是Java应用各线程在某一时刻的运行的位置,即JVM执行到哪一个类、哪一个方法、哪一个行上。它是一个文本文件,打开后可以看到每一个线程的执行栈,以stack trace的显示。通过对JavaCore文件的分析可以得到应用是否“卡”在某一点上,即在某一点运行的时间太长,例如数据库查询,长期得不到响应,最终导致系统崩溃等情况。
HeapDump文件是一个二进制文件,它保存了某一时刻JVM堆中对象使用情况,这种文件需要相应的工具进行分析,如IBM Heap Analyzer这类工具。这类文件最重要的作用就是分析系统中是否存在内存溢出的情况。
怎么生成
这两个文件可以用手工的方式生成,当我们会遇到系统变慢或无响应的情况,这时就以采用手工的方式生成JavaCore及HeapDump文件。
在Unix/Linux上,产生这两个文件的方法如下:
# ps -ef | grep java
user 4616 4582 0 17:30 pts/0 00:00:00 grep java
root 5580 1 0 Oct27 ? 00:02:27 /usr/bin/java -server -XX:PermSize=64M -XX:MaxPermSize=128m -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=/usr/local/tomcat8090/conf/logging.properties -Djava.endorsed.dirs=/usr/local/tomcat8090/endorsed -classpath :/usr/local/tomcat8090/bin/bootstrap.jar -Dcatalina.base=/usr/local/tomcat8090 -Dcatalina.home=/usr/local/tomcat8090 -Djava.io.tmpdir=/usr/local/tomcat8090/temp org.apache.catalina.startup.Bootstrap start
# kill -3 5580 (目前已经不生成)
首先,找出Java进程id ,然后再执行‘kill -3 进程号’的操作,等文件生成后再做一次同样的操作,再产生一组文件。
如何分析
JavaCore文件
两组文件在分析JavaCore时特别有效,因为它可以看出在先后两个时间点上,线程执行的位置,如果发现先后两组数据中同一线程都执行在同一位置,则说明此处可能有问题,因为程序运行是极快的,如果两次均在某一点上,说明这一点耗时是很大的,通过对这两个文件进行分析,查出原因,进而解决问题。
JavaCore文件的头部有一个“Current Thread Details”标记,它记录了JavaCore产生时系统运行的线程id,使用线程id在文件中查找线程的详细信息,该信息中记载了线程运行哪个类的时候造成的JavaCore。
NULL ------------------------------------------------------------------------
0SECTION TITLE subcomponent dump routine
NULL ===============================
1TISIGINFOOUTOFMEMORY received
1TIDATETIME Date: 2011/12/07 at 15:59:42
1TIFILENAME Javacore filename:/usr/WebSphere/AppServer/profiles/WCSProdNode2/javacore19202086.1323298782.txt
NULL ------------------------------------------------------------------------
0SECTION XHPI subcomponent dump routine
NULL ==============================
1XHTIME Wed Dec 7 15:59:42 2011
1XHSIGRECV Unexpected signal -1 received at 0x0 in <unknown>. Processing terminated.
1XHFULLVERSION J2RE 1.4.2 IBM AIX build ca142ifx-20090918 (SR13 FP2)
NULL
1XHCURRENTTHD Current Thread Details
NULL ----------------------
2XHCURRSYSTHD "WebContainer : 5" sys_thread_t:0x45FB5328
3XHNATIVESTACK Native Stack
NULL ------------
3XHSTACKLINEERR unavailable - stack address not valid
:::
:::
0SECTION XM subcomponent dump routine
NULL ============================
NULL
1XMCURTHDINFO Current Thread Details
NULL ----------------------
3XMTHREADINFO "WebContainer : 5" (TID:0x70A8E260, sys_thread_t:0x45FB5328, state:R, native ID:0x5CC0) prio=5
4XESTACKTRACE at org.apache.taglibs.standard.tag.common.core.ImportSupport$ImportResponseWrapper.getString(Unknown Source)
4XESTACKTRACE at org.apache.taglibs.standard.tag.common.core.ImportSupport.acquireString(Unknown Source)
4XESTACKTRACE at org.apache.taglibs.standard.tag.common.core.ImportSupport.doEndTag(Unknown Source)
4XESTACKTRACE at com.ibm._jsp._part._jspx_meth_c_import_3(_part.java(Compiled Code))
4XESTACKTRACE at com.ibm._jsp._part._jspx_meth_c_otherwise_3(_part.java(Compiled Code))
4XESTACKTRACE at com.ibm._jsp._part._jspx_meth_c_choose_4(_part.java(Compiled Code))
4XESTACKTRACE at com.ibm._jsp._part._jspService(_part.java:3237)
这样结合当时的日志文件可以找到问题产生的原因。不过,这种方法只能找到不是内存溢出的错误,对于在core文件头就有java/lang/outMemoryException的错误还是不知道是执行到哪个类的时候出现。
HeapDump文件
HeapDump文件是指定时刻的Java堆栈的快照,是一种镜像文件。Heap Analyzer工具通过分析HeapDump文件,哪些对象占用了太多的堆栈空间,来发现导致内存泄露或者可能引起内存泄露的对象。
其中jmap是java自带的工具
查看整个JVM内存状态
jmap -heap [pid]
要注意的是在使用CMS GC 情况下,jmap -heap的执行有可能会导致JAVA 进程挂起
查看JVM堆中对象详细占用情况
jmap -histo [pid]
导出整个JVM 中内存信息
jmap -dump:format=b,file=文件名 [pid]
jhat是sun 1.6及以上版本中自带的一个用于分析JVM 堆DUMP 文件的工具,基于此工具可分析JVM HEAP 中对象的内存占用情况
jhat -J-Xmx1024M [file]
执行后等待console 中输入start HTTP server on port 7000 即可使用浏览器访问 IP:7000
eclipse Memory Analyzer
Eclipse 提供的一个用于分析JVM 堆Dump文件的插件。借助这个插件可查看对象的内存占用状况,引用关系,分析内存泄露等。
http://www.eclipse.org/mat/
[color=red]kill -3 [pid] (目前已经不生成)
在Linux 上找到Java所在的进程号,然后执行以上命令,线程的相关信息就输出到console
jstack
jstack 是sun JDK 自带的工具,通过该工具可以看到JVM 中线程的运行状况,包括锁等待,线程是否在运行
执行 jstack [pid] ,线程的所有堆栈信息
"http-8080-10" daemon prio=10 tid=x0a949bb60 nid=0x884 waiting for monitor entry [...]
"http-8080-10" 这个线程处于等待状态。 waiting for monitor entry 如果在连续几次输出线程堆栈信息都存在于同一个或多个线程上时,则说明系统中有锁竞争激烈,死锁,或锁饿死的想象。
“http-8080-11” daemon prio=10 tix=xxx nid=xxx in object.wait() [...]
java.lang.Thread.State:waiting (on object monitor)
该表示http-8080-11的线程处于对象的Wait 上,等待其他线程的唤醒,这也是线程池的常见用法。
“Low Memory Detector”daemon prio=10 tix=xx nid=xxx runnable [...] java.lang.Thread.State:runnable
表示“Low Memory Detector” 的线程处于Runable状态,等待获取CPU的使用权.
[/color]
了分析java应用的内存泄漏,使用thread dump往往解决不了问题。使用jstat【eg:jstat -gcutil pid 1000 5】工具查看运行的java应用的heap size,perm size ,survivor ratio等,当时你无法知道是什么对象把堆填满了。
什么是 Java heap dump
首先需要搞懂什么是java heap,java heap是分配给实例类和数组对象运行数据区,所有java线程在运行期间共享heap中的数据。Java heap dump相当于java应用在运行的时候在某个时间点上打了个快照(snapshot)。
触发 Java heap dump
有以下方法出发heap dump
使用$JAVA_HOME/bin/jmap -dump来触发,eg:jmap -dump:format=b,file=/home/longhao/heamdump.out
使用$JAVA_HOME/bin/jcosole中的MBean,到MBean>com.sun.management>HotSpotDiagnostic>操作>dumpHeap中,点击 dumpHeap按钮。生成的dump文件在java应用的根目录下面。
在应用启动时配置相关的参数 -XX:+HeapDumpOnOutOfMemoryError,当应用抛出OutOfMemoryError时生成dump文件。
使用hprof。启动虚拟机加入-Xrunhprof:head=site,会生成java.hprof.txt文件。该配置会导致jvm运行非常的慢,不适合生产环境。
分析 Java heap dump
1:使用IBM HeapAnalyzer
IBM HeapAnalyzer是一款免费的JVM内存堆的图形分析工具,它可以有效的列举堆的内存使用状况,帮助分析Java内存泄漏的原因。
下载解压后有一个ha413.jar,执行: java -Xmx512m -jar ha413.jar /home/longhao/heapdump.out
2:jhat
jhat(Java Head Analyse Tool )是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言OQL,分析相关的应用后,可以通过http://localhost:7000来访问分析结果。
示例: $JAVA_HOME/bin/jhat -J-Xmx512m /home/longhao/dump.out
3:Eclipse MemoryAnalyzer
Eclipse Memory Analyzer是一个快速并且功能强大的Java heap分析器,能够帮助你查找内存泄漏和减少内存消耗。在File>Acquire Heap Dump>configure>HPROF jmap dump provider设置一下分析应用的JDK,点击相关应用列表来生成heap dump并分析。
在socket,nio中的有些API中,申请的内存是直接想OS要的,在堆中分析内存是查看不到的,可以通过-XX:MaxDirectMemorySize=来设置应用向OS直接申请的最大内存数。
1.jmap –heap pid
查看内存
查看指定java进程内的所有对象情况,统计信息
得到运行java程序的内存分配的详细情况。例如实例个数,大小等
命名行格式
jmap [ option ] pid
jmap [ option ] executable core
jmap [ option ] [server-id@]remote-hostname-or-IP
-dump:[live,]format=b,file=<filename> 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件.
-finalizerinfo 打印正等候回收的对象的信息.
-heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.
-histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.
-permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来.
-F 强迫.在pid没有相应的时候使用-dump或者-histo参数. 在这个模式下,live子参数无效.
-h | -help 打印辅助信息
-J 传递参数给jmap启动的jvm.
[wls81@CNSH-stg4-080 ~]$ jmap -heap 1345
Attaching to process ID 1345, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.45-b01
using parallel threads in the new generation. –新生代采用并行线程处理方式
using thread-local object allocation.
Concurrent Mark-Sweep GC –同步并行垃圾回收
Heap Configuration:
MinHeapFreeRatio = 40 –最小堆使用比例,小于40增加
MaxHeapFreeRatio = 70 –最大堆可用比例,大于70缩小
MaxHeapSize = 2147483648 (2048.0MB) –最大堆空间大小
NewSize = 21757952 (20.75MB)-新生代初始值
MaxNewSize = 43581440 (41.5625MB)- 新生代最大值
OldSize = 65404928 (62.375MB)
NewRatio = 7 -新域与旧域之比,如-XX:NewRatio = 7就表示新域与旧域之比为1:7
SurvivorRatio = 8 -新域中Eden区与两个Survivor区的比值
PermSize = 21757952 (20.75MB)
MaxPermSize = 268435456 (256.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 39256064 (37.4375MB)
used = 10106616 (9.638420104980469MB)
free = 29149448 (27.79907989501953MB)
25.745362550866027% used
Eden Space:
capacity = 34930688 (33.3125MB)
used = 8710216 (8.306709289550781MB)
free = 26220472 (25.00579071044922MB)
24.935712689083022% used
From Space:
capacity = 4325376 (4.125MB)
used = 1396400 (1.3317108154296875MB)
free = 2928976 (2.7932891845703125MB)
32.28389855587121% used
To Space:
capacity = 4325376 (4.125MB)
used = 0 (0.0MB)
free = 4325376 (4.125MB)
0.0% used
concurrent mark-sweep generation: --OG大小和使用情况
capacity = 2103902208 (2006.4375MB)
used = 621060520 (592.2894668579102MB)
free = 1482841688 (1414.1480331420898MB)
29.519457588781616% used
Perm Generation:
capacity = 221929472 (211.6484375MB)
used = 141924728 (135.34996795654297MB)
free = 80004744 (76.29846954345703MB)
63.9503742882784% used
2.Jmap -dump:format=b,file=dumpFileName pid
dump命令
1.jstat -gc pid
Jstat 一般用来查看堆内存的实时情况
这是一个比较实用的一个命令,可以观察到classloader,compiler,gc相关信息。可以时时监控资源和性能
jstat -gc 22225 2000 20 没个2秒显示一次,一共显示20次
命令格式
-class:统计class loader行为信息
-compile:统计编译行为信息
-gc:统计jdk gc时heap信息
-gcutil:统计gc时,heap情况
-gccapacity:统计不同的generations(不知道怎么翻译好,包括新生区,老年区,permanent区)相应的heap容量情况
-gccause:统计gc的情况,(同-gcutil)和引起gc的事件
-gcnew:统计gc时,新生代的情况
-gcnewcapacity:统计gc时,新生代heap容量
-gcold:统计gc时,老年区的情况
-gcoldcapacity:统计gc时,老年区heap容量
-gcpermcapacity:统计gc时,permanent区heap容量
S0C:年轻代中第一个survivor(幸存区)的容量 (字节)
S1C:年轻代中第二个survivor(幸存区)的容量 (字节)
S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
EC:年轻代中Eden(伊甸园)的容量 (字节)
EU:年轻代中Eden(伊甸园)目前已使用空间 (字节)
OC:Old代的容量 (字节)
OU:Old代目前已使用空间 (字节)
PC:Perm(持久代)的容量 (字节)
PU:Perm(持久代)目前已使用空间 (字节)
YGC:从应用程序启动到采样时年轻代中gc次数
YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)
FGC:从应用程序启动到采样时old代(全gc)gc次数
FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT:从应用程序启动到采样时gc用的总时间(s)
2.jstat -gcutil pid
S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
E:年轻代中Eden(伊甸园)已使用的占当前容量百分比
O:old代已使用的占当前容量百分比
P:perm代已使用的占当前容量百分比
jstack –l pid
stack –l pid > 111.log 生成线程快照到文件中
虚拟机自带的一种堆栈跟踪工具,生成虚拟机当前的线程快照。查看没有响应的线程出现的原因。
-l 长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表.
jstack能得到运行java程序的java stack和native stack的信息。可以轻松得知当前线程的运行情况,注:这个和thread dump是同样的结果。但是thread dump是用kill -3 pid命令,还是服务器上面少用kill为妙
linux的kill -3指令可以帮我们输出当前进程中所有线程的状态,如哪些线程在运行,哪些在等待,因为什么等待,代码哪一行等待。
kill -3 会将信息输出至控制台,所以使用时,被kill -3的进程最好是nohup启动的。
kill -3并不会影响程序运行,不用担心他把程序杀死了。执行kill -3 后 目前已经失效,jdk不在生成dump文件
jstack除了在正常运行的系统能连接上去以外,在系统已经不能正常提供JMX服务了,但进程还活着的时候,也能连接上去。
使用jstack命令的帮助可以看到,该工具的功能也很强大:
主要分为两个功能:
a. 针对活着的进程做本地的或远程的线程dump;
b. 针对core文件做线程dump。
比如,下面就是一个针对进程做的线程dump:
jstack除了进程活着的时候可以做dump,如果进程crash了,那么系统应该会留下core文件,jstack工具依然能够对core文件做线程dump,
jstack java.core
iostat
查看IO相关信息
发表评论
-
ReentrantLock与Condition
2017-03-17 14:25 532多线程和并发性并不是什么新内容,但是 Java 语言设计中的创 ... -
java linux监控
2017-03-13 17:49 502http://agapple.iteye.com/blog/1 ... -
transient和volatile两个关键字
2017-02-16 09:47 575transient和volatile两个关 ... -
java 锁机制
2016-12-09 13:43 478一段synchronized的代码被 ... -
java 正则表达式
2016-12-02 10:28 522众所周知,在程序开发中,难免会遇到需要匹配、查找、替换、判断字 ... -
java ClassNotFoundException和NoClassDefFoundException的差别
2016-08-17 19:47 911首先从名字上可以看出一类是异常,一类属于错误。异常可以通过异常 ... -
ThreadLocal
2016-07-19 11:10 334ThreadLocal是什么 Thre ... -
java CAS
2016-07-10 14:55 346cas 乐观锁每次不锁定整个线程,在操作之前进行判断。悲观锁独 ... -
concurrenthashmap
2016-07-10 11:11 424hash table虽然性能上不如 ... -
java 线程池的使用
2016-07-10 09:52 3761. 引言 合理利用线程池能够带来三个好处。第一:降低资源消 ... -
java.util.concurrent
2016-07-03 16:24 411我们都知道,在JDK1.5之 ... -
JVM 配置 以及垃圾收集器的选择
2016-04-15 12:36 734JVM监控的关键指标说明: a) FGC的环比增加次数。Zab ... -
jvm实时监控工具
2016-04-09 09:35 469 -
哈希 、一致性哈希、余数式哈希
2016-04-07 16:10 868什么是Hash Hash,一 ... -
jvm dump 相关
2016-03-22 17:22 684http://www.cnblogs.com/edwardla ... -
深入剖析volatile关键字
2016-03-21 16:02 550深入剖析volatile关键字 ... -
java线程安全问题之静态变量、实例变量、局部变量
2016-03-08 12:52 577java多线程编程中,存在很多线程安全问题,至于什么是线程安全 ... -
有状态的bean和无状态的bean的区别
2016-03-08 11:23 1523有状态会话bean :每个用户有自己特有的一个实例,在用户的生 ... -
Java nio详解
2016-01-20 16:30 556http://www.ibm.com/developerwor ... -
java 不定长数组
2015-11-24 15:00 789在调用某个方法时,若是方法的参数个数事先无法确定该如何处理 ...
相关推荐
1,IBM的HeapAnalyzer工具。在我们的应用程序发生内存泄露的时候,会生成heapdump文件 2,IBM的Thread and Monitor Dump Analyzer for Java工具 ...在生成heapdump文件的时候,一般会生成javacore文件。
Java内存分为堆内存(Heap)、栈内存(Stack)、方法区(Method Area)和本地方法栈(Native Method Stack)。其中,堆内存是Java对象的主要存储区域,而栈内存则存储着方法调用的上下文。当程序运行过程中,如果堆...
Java内存分为堆(Heap)、方法区(Method Area)、栈(Stack)、本地方法栈(Native Method Stack)和程序计数器(PC Register)五大部分。HeapAnalyzer主要关注的是堆内存,特别是新生代(Young Generation)、老...
- **jhat**:Java Heap Analysis Tool,配合jmap使用,可以分析heapdump文件,找出内存泄漏等问题。 - **MAT (Memory Analyzer Tool)**:Eclipse提供的一个高级内存分析工具,能够帮助用户分析heapdump,定位内存...
### JStack和Java Thread Dumps分析 #### 一、引言 在Java应用程序开发与维护过程中,时常会遇到性能瓶颈或死锁等问题。这些问题往往难以定位,尤其当系统处于高负载下时,更是如此。此时,`JStack`工具便显得尤为...
与HeapDump文件不同,JavaCore文件侧重于CPU的活动,而HeapDump文件则关注内存的使用情况。 JavaCore文件通常在以下两种情况下产生: 1. 当Java程序遇到致命错误但仍然可以继续运行时。 2. 当Java进程因严重问题而...
Java内存主要分为堆内存(Heap)、方法区(Method Area)、栈内存(Stack)、程序计数器(PC Register)和本地方法栈(Native Method Stack)。其中,堆内存是Java对象的主要存储区域,也是HeapAnalyzer分析的重点。...
功能说明一键式收集Java进程的问题定位信息,包括:Thread Stack和Heap Dump等。监控Java进程使用的CPU,当占用率过高时,自动收集Top信息和Thread Stack。启动、停止、查询、导出飞行记录。使用方法将工具上传到...
为了生成Heap Dump,需要在JVM启动参数中添加`-XX:+HeapDumpOnOutOfMemoryError`和`-XX:HeapDumpPath=<dump_file_path>`,前者设置在内存溢出时生成堆转储,后者指定文件保存位置。 ### 7. 测试类准备 编写简单的...
在Java环境中,内存分为几个区域:堆(Heap)、方法区(Method Area)、栈(Stack)和程序计数器(PC Register)。当应用运行时,不同类型的对象会被分配到这些区域。如果管理不当,可能导致内存泄漏或过度消耗,...
- 获取Heap Dump:在你的Java应用中触发一个heap dump,这可以通过JVM参数配置或者在应用运行时通过操作系统的命令实现。 - 打开MAT:启动MAT并选择"Open Heap Dump",然后导入之前生成的heap dump文件。 - 分析...
- **`ALTER SESSION SET EVENTS 'immediate trace name heapdump_addr level n, addr m'`** - 其中 `m` 为SubHeap的地址。 - `n` 为1时转储SubHeap的摘要,`n` 为2时转储SubHeap的内容。 ##### 8\. Process ...
5. **jstack (Stack Trace for Java)** jstack用于生成Java线程的堆栈跟踪,帮助开发者了解线程的状态,如阻塞、等待等,有助于识别死锁和其他线程问题。 6. **JConsole** JConsole是一个图形界面工具,可以直观...
1. 堆转储(Heap Dump):记录了JVM在某个时间点的内存分配情况,包括对象实例、类加载器、线程等信息,常用于分析内存泄漏。 2. 系统转储(System Dump):包含了JVM的全局信息,如系统属性、线程堆栈、JNI本地方法...
在实践中,通过分析JavaCore和HeapDump文件,可以发现和解决内存问题。养成良好的编程习惯,如及时释放不再需要的对象引用,以及合理使用内存池,都能有效改善应用程序的性能。 总结来说,Java性能调优中的垃圾回收...
ALTER SESSION SET EVENTS ‘immediate trace name heapdump_addr level n, addr m'; 其中m为subheap的地址,n为1转储subheap的摘要,n为2转储subheap的内容。 8. Process State Dump ALTER SESSION SET EVENTS ...
3. **分析崩溃信息**:一旦dump文件加载完成,你可以查看"Call Stack"(调用堆栈)窗口,它展示了程序崩溃时的函数调用顺序。这通常能帮你找到问题的根源。 4. **检查线程和模块**:在"Threads"窗口中,你可以查看...
JVM内存包括堆(Heap)、方法区(Method Area)、栈(Stack)、本地方法栈(Native Method Stack)和程序计数器(PC Register)等部分,每个区域都有其特定的功能和可能引发的问题。 2. **堆内存分析**:堆内存是...
Java内存模型主要分为堆内存(Heap)、栈内存(Stack)、方法区(Method Area)、程序计数器(Program Counter Register)和本地方法栈(Native Method Stack)。其中,堆内存存储对象实例,栈内存保存基本类型和...
Java程序在运行时会占用多种类型的内存,包括堆内存(Heap)、栈内存(Stack)、方法区(Method Area)等。其中,堆内存主要用于存储对象实例,是垃圾回收的主要区域;栈内存则为每个线程分配,用于存储基本类型和...