Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决

前言:
  最近服务器一台机器,经常发现jvm错误日志,因为程序有监控,所以进程能够自动启动,没有产生什么大的影响,利用空闲时间分析下这个问题以及给出最后的解决方案:
jvm出现的致命错误,会在默认工作目录下面生成了hs_err_pid<pid>.log 日志文件。其中包含了导致jvm crash 的重要信息(我们可以在虚拟参数中添加 -XX:ErrorFie=./hss_err_pid<pid>.log指定生成路径。)

包含:日志头文件,导致crash的线程信心,所有的线程信息,安全点和锁信息,堆信息,本地代码缓存,编译事件,gc相关记录,jvm内存映射,jvm启动参数,服务器信息。下面我们来解读一个文件:hs_err_pid6911.log这是爬虫调度程序
日志头文件:
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
日志文件已经详细告诉我们原因了:
进程号6711,本机物理内存不足,同时提供了解决方案:
减轻机器内存负载设置Xmx /xms减少java堆内存空间大小如果是64位的操作系统建议使用64bit java,减少java线程数量减少每个线程堆栈大小-Xss,然后再看看更加详细的原因。

导致crash的线程信息:
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决

这里可以看出导致crash的线程信息,该线程是一个JavaThread,表示执行的是java线程,该线程的其它类型还可能是:
 VMThread jVM内部线程
CompilerThread :用来调用JITing,实时编译装卸class 。 通常,jvm会启动多个线程来处理这部分工作,线程名称后面的数字也会累加,例如:CompilerThread1
GCTaskThread:执行gc的线程
WatcherThread:jvm 周期性任务调度的线程,是一个单例对象。该线程在JVM内使用的比较频繁,比如:定期的内存监控、JVM运行状态监控,还有经常执行jstat 这类命令 查看gc使用情况。
pool-2-thread-62292935表示线程名,[_thread_new,线程已经被创建还没有启动,其它状态如下:
_thread_uninitialized:线程还没有创建,它只在内存原因崩溃的时候才出现
_thread_new:线程已经被创建,但是还没有启动
_thread_in_native:线程正在执行本地代码,一般这种情况很可能是本地代码有问题
_thread_in_vm:线程正在执行虚拟机代码
_thread_in_Java:线程正在执行解释或者编译后的Java代码
_thread_blocked:线程处于阻塞状态
…_trans:以_trans结尾,线程正处于要切换到其它状态的中间状态

id=469表示线程ID,stack(0x00007f67790c1000,0x00007f67791c2000)]表示栈空间,后面的是执行过程中出现的错误:
重点看到这句:V  [libjvm.so+0x4f9e3b]  report_vm_out_of_memory(char const*, int, unsigned long, VMErrorType, char const*)+0x8b 内存不足导致分配失败这就是JVM发生致命的原因所在
接下来就是所有线程信息,看到其中有许多线程处于阻塞状态

Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
其它线程如JVM 内部线程以及WatcherThread:jvm 周期性任务调度的线程
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决

下一部分:安全点和锁信息

Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
所有的状态有:
not at a safepoint 正常运行状态
at safepoint  所有线程都因为虚拟机等待状态而阻塞,等待一个虚拟机操作完成。
synchronizing 一个特殊的虚拟机操作,要求虚拟机内的其它线程保持等待状态
堆信息
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决 Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决

这里我们可以看到 内存分代堆使用详情:包括新生代(Eden、from survivor ,to survivor )老生代因为是1.8这里显示了元空间,下面的“Card table”表示一种卡表,是jvm维护的一种数据结构,用于记录更改对象时的引用,以便gc时遍历更少的table和rootconcurrent mark-sweep generation
CMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用上,这种垃圾回收器非常适合

本地代码缓存
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
这是一块用于编译和保存本地代码的内存;注意是本地代码,它和Metaspace(元空间)是不一样的,元空间是用来存放jvm和java类的元数据的。

编译事件

Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
一共编译了十次,每个jvm错误日志都是如此:

gc相关记录:
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
可以看到gc次数为10次(full gc),这里看到这次GC回收了所有eden space

Deoptimization events (10 events):非优化事件

Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决

Internal exceptions (10 events):内部异常,这里主要是socket 关闭异常
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决

jvm内存映射

Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
JVM加载的库信息,这些信息是虚拟机奔溃时的虚拟内存列表区域。它可以告诉奔溃时哪些类库正在被使用,位置在哪里,还有堆栈和守护等信息
00400000-00401000 r-xp 00000000 ca:10 538684297                          /data/jdk/bin/java 
开始是内存区域,r-xp:权限 r/w/x/p/s  分别表示读/写/执行/私有/共享
00000000 文件内的偏移量,ca:10表示文件位置的majorID和minorID 538684297表示索引节点号 。/data/jdk/bin/java 文件位置

jvm启动参数
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
堆内存大小,新生代大小,开启偏向锁等

系统的环境设置:
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
系统信息

Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
这些都是内存cpu、操作系统等服务器的系统信息
最后一张显示虚拟内存,这里显示swap为0。
Java性能分析及问题解决(二)jvm致命错误导致进程直接挂掉,错误日志分析及解决
总结一下:这个问题主要是指线上服务器部署了许多程序,有些邮件统计是每天定时启动,当这些定时脚本启动时,就占用了机器特别多内存。导致内存负载过高,操作系统就会干掉一些进程,所以解决的办法就是把一些程序移到其它机器或者升级内存空间,也可以采用
日志头文件中介绍的方法。