`

JVM Crash排查分享 - 爆栈

阅读更多

一. JVM爆栈

爆栈是JVM Crash的一种案例,意思是JVM 的栈满(StackOverFlow),使得方法无法获取栈空间,而导致应用crash。爆栈是StackOverFlow的一种,只不过上层调用的是本地方法,才有可能导致出现crash,而非Native方法,则会直接抛出StackOverFlow OOM错误。

如果要分析JVM Crash的原因,需要结合Core文件可以定位导致Crash的代码。

注:在一个程序崩溃时,linux一般会在指定目录下生成一个core文件。core文件仅仅是一个内存映象(同时加上调试信息),主要是用来调试的。

二. TradeCenter JVM Crash现象

TC运行过程中,部分机器的java进程突然就没有了,短信报警随之而来,然后紧急排查原因

 1、查看应用log,例如sys.log

结果:应用crash,应用log中没有明显的错误

 

2、查看dragoon监控,观察当时jvm运行情况,cpu,load等信息

结果:jvm运行正常;cpu和load较为平稳;网络等都正常

 

3、查看linux系统日志文件:执行dmesg或者 cat /var/log/messages

结果:日志文件存在下述错误,日志产生时间和jvm crash时间相同

java[23858]: segfault at 0000000042d76ff8 rip 00000031b140d820 rsp 0000000042d77000 error 6

 

咨询同事后得知,这是内存溢出时linux记录的日志,并且segfault 的出错地址和栈顶地址(rsp)十分接近,因此很有可能是栈内存溢出导致的。

 

三. 处理方案,产生core文件

经过第2步的分析,很有可能是栈内存溢出导致jvm crash,那么接下来就要找到应用中哪个点触发的?

 

1. 临时处理方案,利用crontab自动重启应用

由于TC进程挂掉的时间不定,为了不影响集群的稳定性,写了一个crontab定时程序,每一分钟执行一次,当java进程不存在时,自动重启应用。

 

2. 产生core文件

    2.1) 默认情况下,生产环境是不会产生core文件的。在控制台中执行如下命令:

[admin@vm-ae-qa-10 ~]$ ulimit -c
0

    为0表示,系统默认不生成core dump文件。

 

    2.2) 修改ulimit设置:

[admin@vm-ae-qa-10 ~]$ ulimit -c unlimited
[admin@vm-ae-qa-10 ~]$ ulimit -c
unlimited

    该设置仅仅在session级别生效。所以需要在当前session下重启应用,并等待jvm crash。

 

    2.3) 由于TC进程挂掉的时间不定,我们不可能一直在这里等待,需要让该设置在用户级别生效,此时你可以关闭终端,等jvm crash后再分析core文件。在admin用户根目录下执行:

vi .bash_profile
          在.bash_profile增加一行:ulimit -c unlimited,如下
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin
ulimit -c unlimited
export PATH
           2.4) 重启应用
 
    3. core文件产生位置
    TC crash以后,core文件产生在/home/admin/service/bin,即应用启动脚本所在目录。注:该路径可以配置。
 

     注意: TC集群打开core文件设置后,第一次jvm crash时,并没有产生core文件,非常奇怪。文平咨询了淘宝同学:这种情况偶尔会出现,core文件有时产生不了,多试几次就可以了。后来tc再次发生crash时,core文件在/home/admin/service/bin目录下产生,名称为:core-java-400-11-1366630975

 

四. 分析core文件,三步曲

core文件非常大,使用gdb分析该文件,排查过程分为三步:

第一步:加载core 文件:gdb -c core-java-400-11-1366630975

第二步:获取core文件中线程信息,定位jvm crash时,当前正在运行的线程:info threads

第三步:使用jstack命令分析core文件,获取指定线程id对应的代码信息:jstack /usr/alibaba/java/bin/java core.10011 |more

 

详细排查过程如下:

1. 加载core 文件,在控制台执行gdb -c core-java-400-11-1366630975,执行结果如下

....忽略一些信息....
[New process 409]
[New process 408]
[New process 407]
[New process 406]
[New process 405]
[New process 404]
[New process 403]
[New process 400]
#0 0x00002b0200688a63 in ?? ()
(gdb)
     
2. 获取core文件中线程信息,定位jvm crash时,当前正在运行的线程。在gbd后执行info threads ,如下
....忽略一些信息....
[New process 409]
[New process 408]
[New process 407]
[New process 406]
[New process 405]
[New process 404]
[New process 403]
[New process 400]
#0 0x00002b0200688a63 in ?? ()
(gdb) info threads
   此时会显示很多线程信息,按回车一直到文件最后,找到行头带*号的那一行,就是jvm crash时的线程信息
....忽略一些信息....
6 process 16720 0x0000003bc8a0a899 in ?? ()
5 process 16721 0x0000003bc8a0ab00 in ?? ()
4 process 16729 0x0000003bc8a0ab00 in ?? ()
3 process 16742 0x0000003bc8a0ab00 in ?? ()
2 process 16743 0x0000003bc8a0ab00 in ?? ()
* 1 process 1256 0x00002b0200688a63 in ?? ()
   可以看出,导致jvm crash时的线程id为1256。
3. 退出gdb,执行quit
....忽略一些信息....
4 process 16729 0x0000003bc8a0ab00 in ?? ()
3 process 16742 0x0000003bc8a0ab00 in ?? ()
2 process 16743 0x0000003bc8a0ab00 in ?? ()
* 1 process 1256 0x00002b0200688a63 in ?? ()
(gdb) quit
[admin@tradecenter-service-pub lhx]$
4. 使用jstack命令分析core文件,获取指定线程id对应的代码信息,执行如下
[admin@tradecenter-service-pub lhx]$ jstack /usr/alibaba/java/bin/java core-java-400-11-1366630975 |more
   执行结果如下:
Attaching to core core-java-400-11-1366630975 from executable /usr/alibaba/java/bin/java, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.0-b11
Deadlock Detection:

No deadlocks found.

Thread 16743: (state = BLOCKED)
- sun.misc.Unsafe.park(boolean, long) @bci=0 (Compiled frame; information may be imprecise)
- java.util.concurrent.locks.LockSupport.parkNanos(java.lang.Object, long) @bci=20, line=198 (Compiled frame)
- java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(java.util.concurrent.SynchronousQueue$TransferStack$SNode, boolean, long) @bci=174, line=424 (Compiled frame)
- java.util.concurrent.SynchronousQueue$TransferStack.transfer(java.lang.Object, boolean, long) @bci=102, line=323 (Compiled frame)
- java.util.concurrent.SynchronousQueue.poll(long, java.util.concurrent.TimeUnit) @bci=11, line=874 (Interpreted frame)
- java.util.concurrent.ThreadPoolExecutor.getTask() @bci=62, line=945 (Interpreted frame)
- java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=18, line=907 (Compiled frame)
- java.lang.Thread.run() @bci=11, line=662 (Interpreted frame)


Thread 16742: (state = BLOCKED)
- sun.misc.Unsafe.park(boolean, long) @bci=0 (Compiled frame; information may be imprecise)
... 忽略一些信息 ...
   接下来,就是搜索more出来的信息,搜索关键字1256(导致jvm crash时的线程id为1256),执行/1256,往下翻几页,可以看到下面的信息:
 

 

 

很明显,触发点找到了,在TradeFlowServiceAdaptProxy.preparePay方法发生了递归调用,最终导致爆栈。

 

至此,我们知道了jvm crash的代码块,通过结合该代码的执行场景,系统Crash的场景如下:父类中存在preparePay方法,其方法体是调用子类的preparePay,但是子类没有覆盖父类的preparePay。因此,如果去调用父类的preparePay方法...你应该懂了,如此递归调用父类preparePay方法,最终导致爆栈。

 

四. 爆栈的场景

  1. 应用陷入死循环(应用吃掉异常,陷入死循环异常);递归调用,没有结束条件
  2. 栈顶存在native调用
  • 大小: 109.1 KB
分享到:
评论

相关推荐

    JVM Crash,生成hs_err_pid.log文件

    标题"JVM Crash,生成hs_err_pid.log文件"指的是Java虚拟机在运行过程中遇到了致命问题,导致其终止运行,并自动生成了一个错误日志文件。这个文件通常位于JVM崩溃时的工作目录下,文件名由“hs_err_pid”和进程ID...

    jvm日志解读

    《JVM日志解读——揭示Java虚拟机的秘密》 在Java开发中,JVM(Java Virtual Machine)扮演着至关重要的角色。它负责运行我们的代码,管理内存,执行垃圾收集等。当程序出现异常或者性能问题时,JVM生成的日志文件...

    Android-CrashHandler:Android-CrashHandler 将崩溃日志打印到 sdcardcrash

    本项目"Android-CrashHandler"就是这样一个针对Android平台的自定义异常处理器,它能将崩溃日志保存到设备的SD卡上,路径为`sdcards/crash`目录下。 首先,我们来理解一下Android应用的异常处理机制。在Java语言中...

    crsh.shell.core-1.3.0-beta1.zip

    1. CRaSH Shell:CRaSH提供了一种交互式的控制台,允许开发者在远程服务器上执行命令,进行系统监控、性能分析以及故障排查。它的核心组件`crsh.shell.core-1.3.0-beta1`可能包含了处理命令解析、执行逻辑和与JVM...

    java 虚拟机问题分析大全

    - **Crash文件分析**:当JVM出现异常崩溃时,往往会生成crash文件,通过分析这些文件可以定位到问题发生的具体原因。 - **内存分析**:使用工具如MAT(Memory Analyzer Tool)、VisualVM等分析堆内存和非堆内存的...

    java线上故障分析-线程dump,堆内存分析

    例如,在JVM crash的情况下,通常会在工作目录下自动生成一个error文件,该文件包含了crash时的详细信息,包括但不限于信号类型、错误码、问题发生的框架及堆栈信息。 在提供的案例中,可以看到JVM crash的日志信息...

    IBM内部javacore分析pdf教程文件

    对于那些需要处理复杂Java应用程序故障排查的技术人员来说,这份文档将是非常有用的参考指南。通过对javacore文件的深入研究,技术人员能够更快地定位问题所在,并采取有效的措施来优化系统性能,提高系统的稳定性和...

    java troubleshooting guide for HP-UX.pdf

    ###### 1.1.1 Crash Analysis Tools (崩溃分析工具) - **功能**:这些工具主要用于在应用程序崩溃时获取有关崩溃原因的信息。 - **应用场景**:当Java应用程序出现异常终止时,可以通过这些工具来收集系统状态数据,...

    Linux服务器Java进程消失问题解决

    当 JVM 发生致命错误导致崩溃时,会生成一个 hs_err_pid_xxx.log 这样的文件,该文件包含了导致 JVM Crash 的重要信息,我们可以通过分析该文件定位到导致 JVM Crash 的原因,从而修复保证系统稳定。 默认情况下,...

    java1.8.zip

    首先,"cash"可能是笔误,正确的术语应该是“crash”,意为程序崩溃。Java应用崩溃通常与内存问题、线程死锁、错误的代码实现或不兼容的库有关。在JDK 1.8中,JVM(Java虚拟机)可能会由于以下原因出现奔溃: 1. **...

    Crash:多种语言的虚拟机或程序崩溃

    在IT领域,"Crash:多种语言的虚拟机或程序崩溃"这个标题涉及到的是软件运行过程中遇到的问题,尤其是关于虚拟机(Virtual Machine)和程序执行的稳定性。虚拟机是计算机科学中的一个概念,它允许软件在不同的硬件或...

    Mincraft Error Pack

    解决这些问题通常需要检查Java版本是否兼容,调整JVM参数以优化内存分配,或者排查代码中的并发问题。对于开发者来说,理解Java异常处理机制和熟悉JDK提供的调试工具(如jconsole、jvisualvm)是必不可少的技能。 ...

    CustomCrash:别人做的demo,手机应用崩溃信息

    `Exception`用于程序中可以预见的异常情况,而`Error`通常表示严重的问题,如系统错误或JVM问题,这些情况通常不期望由应用程序代码处理。 2. **自定义异常**:在CustomCrash项目中,可能包含开发者创建的自定义...

Global site tag (gtag.js) - Google Analytics