有一次服务器jvm crash,无任何异常信息。后来想想不对啊,除非是人为的将java的进程kill掉,要不然不可能没有错误日志的,后来突然想起上次价格行情做性能测 试时,当jvm crash掉之后,是在Tomcat下生成一个hs_err_pid**.log文件的,于是找到那个文件,下面是分析过程, 这个文件有几部分内容,首先是头部信息,头信息包含了出错的大体信息和位置。
02 |
# A fatal error has been detected by the Java Runtime Environment: |
04 |
# SIGSEGV ( 0xb ) at pc= 0x00002ad9817ab34e , pid= 10344 , tid= 1083357504
|
06 |
# JRE version: 6 .0_18-b07
|
07 |
# Java VM: Java HotSpot(TM) 64 -Bit Server VM ( 16.0 -b13 mixed mode linux-amd64 )
|
09 |
# V [libjvm.so+ 0x2de34e ]
|
11 |
# If you would like to submit a bug report, please visit: |
在这部分中,有三块内容需要我们注意,一是SIGSEGV是一个信号名称,表示这是一个建立CORE文件段的非法错 误; 二是指明了运行环境,jre版本以及jvm版本;三是最重要的信息,它指明了出错的地方,这里V表示一种frame type,这里是指vmframe,而中括号里则表示出错是在libjvm.so这个文件里,具体位置的偏移量为+号后面的数据。由这里可以知道这是由于 jvm自身运行错误导致。
这个文件的第二部分则是当前处理的线程,或者说是当jvm crash时在运行的线程,详细内容如下:
01 |
--------------- T H R E A D --------------- |
03 |
Current thread ( 0x000000005d835000 ): GCTaskThread [stack: 0x000000004082b000 , 0x000000004092c000 ] [id= 10346 ]
|
05 |
siginfo:si_signo=SIGSEGV: si_errno= 0 , si_code= 128 (), si_addr= 0x0000000000000000
|
08 |
RAX= 0x0000000000000001 , RBX= 0x00002aaab9f2bdd0 , RCX= 0x00002aaaaea56eb8 , RDX= 0x000a000d003e0024
|
09 |
RSP= 0x000000004092aed0 , RBP= 0x000000004092aef0 , RSI= 0x00002aaab9f2bdd0 , RDI= 0x000000005d883780
|
10 |
R8 = 0x00002aaaaea56d80 , R9 = 0x0000000000000001 , R10= 0x00002ad981de7201 , R11= 0x00002ad981df46e0
|
11 |
R12= 0x000000005d883780 , R13= 0x00002aaaaea56eb8 , R14= 0x00002aaaaea56eb8 , R15= 0x000000005d883780
|
12 |
RIP= 0x00002ad9817ab34e , EFL= 0x0000000000010202 , CSGSFS= 0x0000000000000033 , ERR= 0x0000000000000000
|
13 |
TRAPNO= 0x000000000000000d
|
15 |
Top of Stack: (sp= 0x000000004092aed0 )
|
16 |
0x000000004092aed0 : 000000004092af00 00002ad9817ab3be
|
17 |
0x000000004092aee0 : 00002aaab9f2bdd0 00002aaab9f2bdd0
|
这里只要第一行即可,这一行指明了,当crash时,程序正在运行垃圾回收线程,所以有理由怀疑是垃圾回收出了问题,然后这个文件就指引我们来到了第三部分,dump出来的线程信息。
01 |
--------------- P R O C E S S --------------- |
02 |
Java Threads: ( => current thread ) |
03 |
0x0000000056523000 JavaThread "Keep-Alive-Timer" daemon [_thread_blocked, id= 12281 ,
|
04 |
stack( 0x00000000478cc000 , 0x00000000479cd000 )]
|
05 |
0x0000000056a2e000 JavaThread "pool-7-thread-3" [_thread_blocked, id= 8876 , stack
|
06 |
( 0x0000000046fc3000 , 0x00000000470c4000 )]
|
07 |
0x000000005687f800 JavaThread "ClientConnectionHandler" daemon [_thread_in_native,
|
08 |
id= 4786 , stack( 0x0000000044599000 , 0x000000004469a000 )]
|
09 |
0x0000000056d0b000 JavaThread "MERGE2.FindSubgroups thread (channel=*******)"
|
10 |
daemon [_thread_blocked, id= 4710 , stack( 0x00000000472c6000 , 0x00000000473c7000 )]
|
11 |
0x0000000056796800 JavaThread "pool-7-thread-2" [_thread_blocked, id= 6325 , stack
|
12 |
( 0x00000000477cb000 , 0x00000000478cc000 )]
|
16 |
PSYoungGen total 160448K, used 154320K [ 0x00002aaac8b60000 , 0x00002aaad2fc0000 ,
|
18 |
eden space 152448K, 100 % used [ 0x00002aaac8b60000 , 0x00002aaad2040000 , 0x00002aaad2040000 )
|
19 |
from space 8000K, 23 % used [ 0x00002aaad27f0000 , 0x00002aaad29c4018 , 0x00002aaad2fc0000 )
|
20 |
to space 7872K, 12 % used [ 0x00002aaad2040000 , 0x00002aaad2134018 , 0x00002aaad27f0000 )
|
21 |
PSOldGen total 349568K, used 344605K [ 0x00002aaab3600000 , 0x00002aaac8b60000 ,
|
23 |
object space 349568K, 98 % used [ 0x00002aaab3600000 , 0x00002aaac8687690 , 0x00002aaac8b60000 )
|
24 |
PSPermGen total 65792K, used 48038K [ 0x00002aaaae200000 , 0x00002aaab2240000 ,
|
26 |
object space 65792K, 73 % used [ 0x00002aaaae200000 , 0x00002aaab10e9bf8 , 0x00002aaab2240000 )
|
30 |
jvm_args: -Xms128m -Xmx512m -XX:PermSize=64m -Djava.net.preferIPv4Stack= true -Drialto.command.port= 6789 -Drialto.work.dir=/home/admin/output/work
|
31 |
java_command: com.******.*****.*****.apptask.CheckTaskStart |
32 |
Launcher Type: SUN_STANDARD |
33 |
Environment Variables: |
34 |
JAVA_HOME=/usr /*****/ java
|
35 |
PATH=/usr /*****/ java/bin:/usr /******/ ant/bin:/usr /******/ antx- 2 /bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/admin/bin
|
36 |
LD_LIBRARY_PATH=/usr /*******/ install/jdk1. 6 .0_18/jre/lib/amd64/server:/usr /******/ install/jdk1. 6 .0_18/jre/lib/amd64:/usr /******/ install/jdk1. 6 .0_18/jre/../lib/amd64
|
在略过上面N行的处于bolcked状态下的线程信 息后,我们终于看到了此时的堆信息。由标红处我们发现,crash正处于eden区达到了100%要进行young gc的时候,因此我们有理由相信是由于young gc出了问题所致。但是什么问题呢?于是上google搜了一下“jvm crash young gc”。good luck!第一篇就找到了相应的解决方法,原来是这是jdk1.6u18的一个bug,官方文档介绍如下:
1 |
Card-Marking Optimization Issue |
2 |
A flaw in the implementation of a card-marking performance optimization in the JVM can cause heap corruption under some circumstances. This issue affects the CMS garbage collector prior to 6u18, and the CMS, G1 and Parallel Garbage Collectors in 6u18. The serial garbage collector is not affected. Applications most likely to be affected by this issue are those that allocate very large objects which would not normally fit in Eden, or those that make extensive use of JNI Critical Sections (JNI Get/Release*Critical).
|
3 |
This issue will be fixed in the next Java SE 6 update.
|
4 |
Meanwhile, as a workaround to the issue, users should disable this performance optimization by -XX:-ReduceInitialCardMarks.
|
这段话主要三个意思:一是指这个bug影响的GC类型为1.6u18前的CMS类GC以及1.6u18的CMS、G1和并行类GC,而串行GC不受影 响;二是指哪些程序会受影响,主要是那些会分配大量的大对象而eden区过小或者对JNI使用比较敏感的程序;三是指明了处理方法
那么此处是否符合前面的两个条件呢?通过JVM参数,我们发现本例中的GC类型未指定,也就是使用的是默认参数,那么默认的GC类型是什么呢?在 JDK5.0之前默认的GC是串行GC,但是之后尤其是到了JDK6.0之后就更加智能化了,会依据机器的性能来进行指定,怎么个指定法呢?有以下三条原 则:
1、如果你是使用服务器类JVM的话,那么就会由并行GC来取代串行GC;
2、当程序运行后,会首先去检查硬件环境,如果确定其性能满足服务器类机器的标准的话,就会运行服务器类JVM
3、什么样的机器符合服务器类的标准呢?CPU至少要在2核以上,物理内存在2G以上。
通过以上三条,可以确认任务机符合服务器类机器的标准,因此会使用并行GC,在这个bug的影响范围内。而对于第二点,JVM参数只指定了512M内存, 除去永久区的64M,而新生代与老生代的默认分配比例是1:8,因此新生代大约是在50M左右,的确不是一个很大的数字。当初也许是由于担心任务和web 跑在一台机器上吧,因此将JVM的堆参数设得这么小。
后续的处理方法一是将任务的JVM参数标准化;二是使用-XX:-ReduceInitialCardMarks来解决这个bug!
参考原文来自:http://blog.csdn.net/hpsysljt/article/details/6388082
分享到:
相关推荐
本文将深入探讨如何查看和分析JVM的内存状态,特别是通过输出GC日志。 首先,让我们了解JVM内存的基本结构。JVM内存主要分为年轻代(Young Generation)、老年代(Old Generation)和永久代(Permanent Generation...
要查看JVM中的线程信息,可以使用`ThreadMXBean`的静态工厂方法`ManagementFactory.getThreadMXBean()`获取实例,然后调用相关方法。以下是一个简单的示例代码(参考文件`ThreadAction.java`): ```java import ...
代码如下:failed to create jvm error code -4 这一般应是内存不够用所致,解决方法参考如下。 打开 Android Studio 安装目录下的bin目录,查找并打开文件 studio.exe.vmoptions,修改代码: 代码如下:-Xmx512m 为...
堆存储对象实例,方法区存放类信息,程序计数器记录当前线程执行的指令地址,虚拟机栈保存每个方法的局部变量、操作数栈等,本地方法栈为JNI调用的本地方法服务。 3. 指令集:JVM使用一套基于栈的指令集,这些指令...
本文将深入探讨一个具体的JNI调用导致JVM(Java虚拟机)报错的问题。 首先,让我们看看给出的Java代码示例: ```java package jni; public class JNITransObject { public native TestJNI[] ObjectMethod(String...
在这个压缩包中,"JVM图解.png"可能是对JVM内部结构的可视化表示,"JVM图解"可能是一个详细的文档,解释了JVM的工作原理,而"JVM指令手册 中文版"则提供了JVM可执行的所有指令的详细信息。下面,我们将深入探讨JVM的...
标题中提到了JVM原理、JVM调优、JVM内存模型和JAVA并发,这些都是Java虚拟机(JVM)相关的核心概念。JVM是运行Java字节码的虚拟计算机,为Java提供了一个跨平台的环境,确保Java程序可以在不同的操作系统上运行而...
这里提到的“查看工具”是指用于监控和分析JVM性能的工具,其中就包含了Java VisualVM。Java VisualVM(也被称为JVisualVM)是Java开发工具包(JDK)自带的一个多用途的JVM诊断工具。它提供了CPU和内存使用情况的...
本系列课程从JVM基础到高级实战,老师手把手教你如何进行JVM调优,思路清晰,没有废话,旨在挑战高薪。 课程亮点: 1、基于阿里arthas进行JVM调优; 2、基于代码排查OOM问题,拒绝空讲; 3、总结JVM通用的调优思路;...
- `src.zip`:包含了源代码,允许开发者查看和分析SAP JVM的实现细节,便于调试和学习。 - `bin`:包含了可执行文件和脚本,用户可以直接运行这些文件启动JVM。 - `include`:包含了头文件,供C/C++程序链接到...
Java虚拟机(JVM)是Java程序运行的基础,它是一个抽象的计算机系统,负责执行Java字节码。本文将深入探讨JVM的启动过程及其基本原理。 首先,我们需要理解JVM的基本概念。JVM是Java Virtual Machine的缩写,它是...
### JVM 详细介绍:掌握 JVM 的各个组成部分与功能 #### 一、Java 源文件编译及执行 Java 应用程序的核心在于源文件的编译与执行。不同于 C/C++ 这类需要针对不同平台进行编译的语言,Java 采用了一种更为灵活的...
linux 下用java 获取系统信息 cpu mem jvm等 用java调用系统命令得到,方便实用
通过查看对象分配图表,可以发现哪些类或方法在消耗大量内存,从而定位潜在的问题。 2. **垃圾收集分析**:JProfiler11提供了GC日志分析,可以观察不同垃圾收集器的执行频率和效果,帮助优化垃圾回收策略,减少不必...
1. **COPYRIGHT**:这个文件通常包含软件的版权信息和许可协议,详细列出了SAP JVM的知识产权归属以及用户可以如何合法使用该软件。了解这些信息对于遵循法律和避免潜在的侵权行为至关重要。 2. **README.txt**:这...
EBS R11,打开时IE报错,更新该DLL文件后,文件解决。
JVM(Java Virtual Machine,Java虚拟机)是运行所有Java程序的假想计算机,是Java程序的运行环境,负责执行指令、管理数据、内存、寄存器等,是实现Java跨平台特性的关键部分。JVM指令手册详细记录了JVM的所有操作...
`jmap`是Java的一个命令行工具,用于获取堆内存的详细信息,包括堆dump,这对于分析JVM内存状态非常有用。 本文将深入探讨JVM内存结构、`jmap`工具的使用以及如何分析`dump.txt`文件中的内存日志。 1. JVM内存结构...
6. **系统资源监控**:除了JVM内部,`jvm-mon`还能提供操作系统级别的信息,如CPU、内存和磁盘使用情况,以全面了解系统健康状况。 ### 使用jvm-mon 要使用`jvm-mon`,首先需要从源代码仓库(如GitHub)克隆或下载...