Java系统宕机之进程闪退
前言
闪退在打开或使用应用程序时出现的突然退出中断的情况(类似于Windows的应用程序崩溃)。多表现为:应用程序画面一闪而过,随即退回到桌面。
一、内部崩溃
JVM 发生内部崩溃,那么必然会生成"hs_err_pid"开头的文件,下面讲一种常见情况:无法申请内存,显示commit_memory错误。
Current thread (0x00007f3e40013000): JavaThread "Unknown thread" [_thread_in_vm, id=11408, stack(0x00007f3e49983000,0x00007f3e49a84000)]
Stack: [0x00007f3e49983000,0x00007f3e49a84000], sp=0x00007f3e49a82360, free space=1020k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0x9a32da] VMError::report_and_die()+0x2ea
V [libjvm.so+0x497f7b] report_vm_out_of_memory(char const*, int, unsigned long, char const*)+0x9b
V [libjvm.so+0x81fcce] os::Linux::commit_memory_impl(char*, unsigned long, bool)+0xfe
V [libjvm.so+0x820219] os::pd_commit_memory(char*, unsigned long, unsigned long, bool)+0x29
V [libjvm.so+0x819faa] os::commit_memory(char*, unsigned long, unsigned long, bool)+0x2a
V [libjvm.so+0x99eae9] VirtualSpace::expand_by(unsigned long, bool)+0x1c9
V [libjvm.so+0x99ec6d] VirtualSpace::initialize(ReservedSpace, unsigned long)+0xcd
V [libjvm.so+0x57962f] CardGeneration::CardGeneration(ReservedSpace, unsigned long, int, GenRemSet*)+0x11f
V [libjvm.so+0x46ceed] ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(ReservedSpace, unsigned long, int, CardTableRS*, bool, FreeBlockDictionary<FreeChunk>::DictionaryChoice)+0x5d
V [libjvm.so+0x57a906] GenerationSpec::init(ReservedSpace, int, GenRemSet*)+0x106
V [libjvm.so+0x56afe4] GenCollectedHeap::initialize()+0x344
V [libjvm.so+0x9751aa] Universe::initialize_heap()+0xca
V [libjvm.so+0x976379] universe_init()+0x79
V [libjvm.so+0x5b1d25] init_globals()+0x65
V [libjvm.so+0x95dc6d] Threads::create_vm(JavaVMInitArgs*, bool*)+0x1ed
V [libjvm.so+0x639fe4] JNI_CreateJavaVM+0x74
这一般是因为 Xmx 设置过大,超过系统可用内存,JVM 申请内存失败。比如服务器总内存32G ,同时运行多个程序,程序 A 配了20G的Xmx,其他程序也配了20G Xmx ,Linux的交换空间也没有设置,这时候如果其他程序用满20G的内存那么服务的可用内存必然低于12G,这时如果Tomcat需要大于12G的内存就很容易发生该错误,直接宕机。
解决方案
减少Xmx值使得所有的综合不超过服务器物理内存
调整 Xms=Xmx
服务器不要运行其他不必要的东西
配置一部分swap空间(虚拟内存)
二、外部终止
如果找不到"hs_err_pid"开头的文件那么,这个进程的闪退必然是被从外部终止的。
OOMKiller
java长期内存占用过高,系统需要内存使用的时候没有内存,Linux的oomkiller机制会干掉最低优先级的内存。检查 /var/logs/message , /var/logs/dmesg或者对应日期文件,看看有没有类似下面的内容,日志有时间可以判断。
SSH注销
检查/var/log/auth.log,/var/log/secure或者对应日期的文件,检查宕机的时间点有没有。
上图可以看出时间吻合,那么宕机原因即可确认。
解决方案
使用nohup命令在后台运行启动程序,检查ssh注销原因
总结
宕机分析的目的就是要找到占用内存的进程,分析相应原因,然后修改替换。