参考:https://blog.csdn.net/tototuzuoquan/article/details/108912419
https://www.cnblogs.com/yelao/p/9814467.html
throwable中包括exception(异常)和error(错误)
查看进程的句柄:
ls /proc/29347/fd
当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽
ls|wc -l的结果是文件个数,ls -l|wc -l的结果是文件个数+1。
ls |wc -l文件个数
1、可以使用三方arthas,但需要下载完整版本,只是jar不行。并且还需要jps。
2、下载的core文件,通过gcc的,gdb java core ,之后bt查看崩溃原因。
3、jstack、jmap等
JVM Crash崩溃的日志,一般生成在工作目录下,当然也可以通过JVM指定生成路径,如:
-XX:ErrorFile=/var/log/hs_err_pid<pid>.log
对于hs_err_pid.log文件,头文件如下:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGBUS (0xa) at pc=0x00007fffea0359fc, pid=51419, tid=0x0000000000000002
#
# JRE version: Java(TM) SE Runtime Environment (8.0_201-b09) (build 1.8.0_201-b09)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.201-b09 mixed mode solaris-sparc compressed oops)
# Problematic frame:
# C [libproc.so.1+0x359fc] proc_grab_common+0x24
#
# Core dump written. Default location: /export/home/springbootDemo_jar/core or core.51419
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
这段内容主要简述了导致 JVM Crash 的原因。常见的原因有 JVM 自身的 bug,应用程序错误,JVM 参数,服务器资源不足,JNI 调用错误等。
SIGBUS意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。通常是未对齐的数据访问所致。
这里一个重要信息是SIGBUS (0xa)
表示jvm crash
时正在执行线程试图访问一块无文件内容对应的内存区域,比如超过文件尾的内存区域,或者以前有文件内容对应,现在为另一进程截断过的内存区域。其中SISBUS
是信号名称,0xa
是信号码,pc=0x00007fffea0359fc
指的是程序计数器的值,pid=51419
是进程号,tid=0x0000000000000002
是线程号。
其他错误参考:
SIGSEGV (0xb) at pc=0x0000003797807a91, pid=29071, tid=139901421901568
SIGSEGV(0xb) 表示 JVM Crash 时正在执行 JNI 代码,常见的描述还有EXCEPTION_ACCESS_VIOLATION,该描述表示 JVM Crash 时正在执行 JVM 自身的代码,这往往是因为 JVM 的 Bug 导致的 Crash;另一种常见的描述是EXCEPTION_STACK_OVERFLOW,该描述表示这是个栈溢出导致的错误,这往往是应用程序中存在深层递归导致的。
文件头中有很多有用的信息,“EXCEPTION_ACCESS_VIOLATION ”意味着Java应用Crash的时候,正在运行JVM自己的代码,而不是外部的Java代码或其他类库代码。这种情况很可能是JVM的Bug,但是也不一定。除了“EXCEPTION_ACCESS_VIOLATION ”,还有可能是别的信息,例如“SIGSEGV(0xb)”,意味着JVM正在执行本地或JNI的代码;“EXCEPTION_STACK_OVERFLOW”意味着这是个栈溢出的错误。(**********看到这里我们知道我报错时正在运行JVM自己的代码,而不是外部的Java代码或其他类库代码*********)
# Problematic frame:
# C [libproc.so.1+0x359fc] proc_grab_common+0x24
这个信息比较重要,问题帧信息:
C 表示帧类型为本地帧;j : 解释的Java帧;V : 虚拟机帧;v :虚拟机生成的存根栈帧;J:其他帧类型,包括编译后的Java帧。
[libproc.so.1+0x359fc] proc_grab_common+0x24 和程序计数器(pc)表达的含义一样,但是用的是本地so库+偏移量的方式。。
导致 crash 的线程信息:
--------------- T H R E A D ---------------
Current thread (0x000000010010b800): JavaThread "main" [_thread_in_native, id=2, stack(0xffffffff7f1f0000,0xffffffff7f2f0000)]
siginfo: si_signo: 10 (SIGBUS), si_code: 1 (BUS_ADRALN), si_addr: 0x0000000000000004
Registers:
G1=0x0000000000102620 G2=0x0000000000000000 G3=0x00007ffff450bf09 G4=0x0000000000077f79
G5=0xffffffff7f54afd8 G6=0x0000000000000000 G7=0xffffffff7f560240 Y=0x0000000000000000
O0=0x0000000000000000 O1=0x0000000000000000 O2=0x0000000000000000 O3=0x0000000000000000
O4=0x0000000000000000 O5=0x0000000000000000 O6=0xffffffff7f2ec8d1 O7=0x0000000000000000
L0=0x0000000000000000 L1=0x0000000000000000 L2=0x0000000000000000 L3=0x00007fffea138000
L4=0x0000000000000000 L5=0x0000000000000000 L6=0x0000000000000000 L7=0x0000000000000000
I0=0x0000000100688040 I1=0x0000000000000002 I2=0x0000000000000002 I3=0xffffffff7f2edb38
I4=0x0000000000000004 I5=0x0000000000000000 I6=0xffffffff7f2ecb41 I7=0x00007fffea035dbc
PC=0x00007fffea0359fc nPC=0x00007fffea035a00
Top of Stack: (sp=0xffffffff7f2ed0d0)
0xffffffff7f2ed0d0: 0000000000000000 0000000000000000
0xffffffff7f2ed0e0: 0000000000000000 00007fffea138000
0xffffffff7f2ed0f0: 0000000000000000 0000000000000000
0xffffffff7f2ed100: 0000000000000000 0000000000000000
0xffffffff7f2ed110: 0000000100688040 0000000000000002
0xffffffff7f2ed120: 0000000000000002 ffffffff7f2edb38
0xffffffff7f2ed130: 0000000000000004 0000000000000000
0xffffffff7f2ed140: ffffffff7f2ecb41 00007fffea035dbc
0xffffffff7f2ed150: 0000000100327f90 ffffffff5b816b30
0xffffffff7f2ed160: 000000010010b800 ffffffff5b816b30
0xffffffff7f2ed170: 000000010067f900 ffffffff5b4176e8
0xffffffff7f2ed180: 0000000000000000 00000005d5834f60
0xffffffff7f2ed190: 0000000000000000 0000000000000000
0xffffffff7f2ed1a0: 00007fffea2013c2 ffffffff7f4ece98
0xffffffff7f2ed1b0: 00007fffea003df8 0000000100000001
0xffffffff7f2ed1c0: 000000005b816b30 000000010010b800
Instructions: (pc=0x00007fffea0359fc)
0x00007fffea0359dc: ee 5f a8 af a7 41 40 00 03 00 04 09 82 00 62 20
0x00007fffea0359ec: ee 77 a6 3f a6 00 40 13 02 c7 00 05 c0 26 e0 00
0x00007fffea0359fc: c0 77 20 00 10 80 00 05 90 10 00 18 02 cf 00 82
0x00007fffea035a0c: 80 8e 60 01 90 10 00 18 40 04 0d 23 92 10 20 2f
Register to memory mapping:
G1=0x0000000000102620 is an unknown value
G2=0x0000000000000000 is an unknown value
G3=0x00007ffff450bf09: __1cPGenerationSizerG__vtbl_+0x331 in /usr/jdk/instances/jdk1.8.0_201/jre/lib/sparcv9/server/libjvm.so at 0x00007ffff3500000
G4=0x0000000000077f79 is an unknown value
G5=0xffffffff7f54afd8: _PROCEDURE_LINKAGE_TABLE_+0x40d8 in /lib/sparcv9/ld.so.1 at 0xffffffff7f300000
G6=0x0000000000000000 is an unknown value
G7=0xffffffff7f560240 is an unknown value
。。。。。。。。。。。。。。
这部分内容包含出发 JVM 致命错误的线程详细信息和线程栈。
Current thread (0x000000010010b800): JavaThread "main" [_thread_in_native, id=2, stack(0xffffffff7f1f0000,0xffffffff7f2f0000)]
siginfo: si_signo: 10 (SIGBUS), si_code: 1 (BUS_ADRALN), si_addr: 0x0000000000000004
- 0x000000010010b800:出错的线程指针
- JavaThread:线程类型,可能的类型包括
JavaThread:Java线程
VMThread : JVM 的内部线程
CompilerThread:用来调用JITing,实时编译装卸class 。 通常,jvm会启动多个线程来处理这部分工作,线程名称后面的数字也会累加,例如:CompilerThread1
GCTaskThread:执行gc的线程
WatcherThread:JVM 周期性任务调度的线程,是一个单例对象
ConcurrentMarkSweepThread:jvm在进行CMS GC的时候,会创建一个该线程去进行GC,该线程被创建的同时会创建一个SurrogateLockerThread(简称SLT)线程并且启动它,SLT启动之后,处于等待阶段。CMST开始GC时,会发一个消息给SLT让它去获取Java层Reference对象的全局锁:Lock
main:线程名称,
_thread_in_native:当前线程状态。该描述还包含有:
_thread_in_native:线程当前状态,状态枚举包括:
_thread_uninitialized:线程还没有创建,它只在内存原因崩溃的时候才出现
_thread_new:线程已经被创建,但是还没有启动
_thread_in_native:线程正在执行本地代码,一般这种情况很可能是本地代码有问题
_thread_in_vm:线程正在执行虚拟机代码
_thread_in_Java:线程正在执行解释或者编译后的Java代码
_thread_blocked:线程处于阻塞状态
…_trans:以_trans结尾,线程正处于要切换到其它状态的中间状态
Thread in native其实是通过JMI接口去执行了 c和c++的一些native的code,在这种状态下,其实在JMI中已经认为它进入了safepoint,即使已经在运行,与前面提到的stop the world好像理解上有点不一样,这时候这个线程其实还是可以一直在运行的,因为如果这个代码是native的code,其实hotstpot是没法知道是什么状态的,而且也没法控制行为,有可能在做一个很长的 Loop,在那里不停的执行,所以这个时候如果要等的话,肯定会出问题safepoint就进不去了,但这时候认为已经是safepoint了,就可以做那些vm operation,因为我的Java线上还在运行,当 native code执行自己的东西的时候,是不会去碰到那些Java内部的那些hip hop object的那些东西,当想访问那些object的时候,需要通过那些JMI的接口,当调用接口的时候,这个时候JVM就会来检查这时候是不是正在做safepoint,如果正在做safepoint,就会把调用给阻塞,然后线程就会被停下来,等vm operation结束了以后再继续执行下去。 所以虽然在Thread in native状态你仍然在运行,但实际上不会造成造成危害,因为要访问那种Java object或者访问hip的时候,这里的JMI接口会挡住。
- id=2:线程ID
- stack(0xffffffff7f1f0000,0xffffffff7f2f0000)]:栈区间
siginfo: si_signo: 10 (SIGBUS), si_code: 1 (BUS_ADRALN), si_addr: 0x0000000000000004
这部分是导致虚拟机终止的非预期的信号信息:其中si_signo
和si_code
是Linux
下用来鉴别异常的
其他:线程栈信息。包含了地址、栈顶、栈计数器和线程尚未使用的栈信息。到这里就基本上已经确定了问题所在原因了。
线程信息
--------------- P R O C E S S ---------------
Java Threads: ( => current thread )
0x0000000100609800 JavaThread "Service Thread" daemon [_thread_blocked, id=212, stack(0xffffffff01760000,0xffffffff01860000)]
0x0000000100606800 JavaThread "C1 CompilerThread39" daemon [_thread_blocked, id=211, stack(0xffffffff01870000,0xffffffff01970000)]
0x0000000100604800 JavaThread "C1 CompilerThread38" daemon [_thread_blocked, id=210, stack(0xffffffff01980000,0xffffffff01a80000)]
0x0000000100602800 JavaThread "C1 CompilerThread37" daemon [_thread_blocked, id=209, stack(0xffffffff01a90000,0xffffffff01b90000)]
0x0000000100600800 JavaThread "C1 CompilerThread36" daemon [_thread_blocked, id=208, stack(0xffffffff01ba0000,0xffffffff01ca0000)]
0x00000001005fe800 JavaThread "C1 CompilerThread35" daemon [_thread_blocked, id=207, stack(0xffffffff01cb0000,0xffffffff01db0000)]
0x00000001005fd000 JavaThread "C1 CompilerThread34" daemon [_thread_blocked, id=206, stack(0xffffffff01dc0000,0xffffffff01ec0000)]
0x00000001005fb000 JavaThread "C1 CompilerThread33" daemon [_thread_blocked, id=205, stack(0xffffffff01ed0000,0xffffffff01fd0000)]
0x00000001005f9000 JavaThread "C1 CompilerThread32" daemon [_thread_blocked, id=204, stack(0xffffffff01fe0000,0xffffffff020e0000)]
0x00000001005f7000 JavaThread "C1 CompilerThread31" daemon [_thread_blocked, id=203, stack(0xffffffff020f0000,0xffffffff021f0000)]
0x00000001005e4000 JavaThread "C1 CompilerThread30" daemon [_thread_blocked, id=202, stack(0xffffffff02200000,0xffffffff02300000)]
0x00000001005d7800 JavaThread "C1 CompilerThread29" daemon [_thread_blocked, id=201, stack(0xffffffff02310000,0xffffffff02410000)]
0x00000001005c5000 JavaThread "C1 CompilerThread28" daemon [_thread_blocked, id=200, stack(0xffffffff02420000,0xffffffff02520000)]
0x00000001005ba800 JavaThread "C1 CompilerThrea
所有线程信息,一目了然。_thread_blocked表示阻塞。
安全点和锁信息
VM state:not at safepoint (normal execution)
VM Mutex/Monitor currently owned by a thread: None
虚拟机状态。not at safepoint 表示正常运行。其余状态:
- at safepoint:所有线程都因为虚拟机等待状态而阻塞,等待一个虚拟机操作完成;
- synchronizing:一个特殊的虚拟机操作,要求虚拟机内的其它线程保持等待状态。
虚拟机的 Mutex 和 Monito r目前没有被线程持有。Mutex 是虚拟机内部的锁,而 Monitor 则关联到了 Java 对象。
堆信息
heap address: 0x0000000180400000, size: 26620 MB, Compressed Oops mode: Zero based, Oop shift amount: 3
Narrow klass base: 0x0000000800000000, Narrow klass shift: 0
Compressed class space size: 1073741824 Address: 0x0000000800000000
Heap:
PSYoungGen total 2048K, used 1353K [0x00000005d5700000, 0x00000005d5980000, 0x0000000800000000)
eden space 1536K, 88% used [0x00000005d5700000,0x00000005d5852580,0x00000005d5880000)
from space 512K, 0% used [0x00000005d5900000,0x00000005d5900000,0x00000005d5980000)
to space 512K, 0% used [0x00000005d5880000,0x00000005d5880000,0x00000005d5900000)
ParOldGen total 5632K, used 0K [0x0000000180400000, 0x0000000180980000, 0x00000005d5700000)
object space 5632K, 0% used [0x0000000180400000,0x0000000180400000,0x0000000180980000)
Metaspace used 3008K, capacity 4728K, committed 4864K, reserved 1056768K
class space used 324K, capacity 424K, committed 512K, reserved 1048576K
Card table byte_map: [0xffffffff6c800000,0xffffffff6fc00000] byte_map_base: 0xffffffff6bbfe000
新生代、老年代、元空间一目了然。
Card table表示一种卡表,是 jvm 维护的一种数据结构,用于记录更改对象时的引用,以便 gc 时遍历更少的 table 和 root。
本地代码缓存
CodeCache: size=245760Kb used=7908Kb max_used=7908Kb free=237851Kb
bounds [0xffffffff70000000, 0xffffffff707c0000, 0xffffffff7f000000]
total_blobs=316 nmethods=68 adapters=154
compilation: enabled
编译事件
Compilation events (10 events):
Event: 0.161 Thread 0x00000001005fe800 64 3 java.nio.Buffer::checkIndex (22 bytes)
Event: 0.161 Thread 0x00000001005f7000 65 3 java.nio.DirectLongBufferU::ix (10 bytes)
Event: 0.162 Thread 0x00000001005f7000 nmethod 65 0xffffffff707b7710 code [0xffffffff707b7860, 0xffffffff707b7a00]
Event: 0.162 Thread 0x00000001005fe800 nmethod 64 0xffffffff707b7a90 code [0xffffffff707b7c20, 0xffffffff707b7f40]
Event: 0.162 Thread 0x0000000100600800 66 1 java.security.ProtectionDomain::getCodeSource (5 bytes)
Event: 0.162 Thread 0x0000000100600800 nmethod 66 0xffffffff707b8010 code [0xffffffff707b8140, 0xffffffff707b8260]
Event: 0.162 Thread 0x00000001005c5000 67 3 java.lang.AbstractStringBuilder::<init> (12 bytes)
Event: 0.162 Thread 0x00000001005c5000 nmethod 67 0xffffffff707b82d0 code [0xffffffff707b8440, 0xffffffff707b8740]
Event: 0.163 Thread 0x00000001005fd000 68 3 sun.misc.MetaIndex::mayContain (51 bytes)
Event: 0.163 Thread 0x00000001005fd000 nmethod 68 0xffffffff707b8810 code [0xffffffff707b8a40, 0xffffffff707b9148]
gc 日志
GC Heap History (0 events):
No events
Deoptimization events (0 events):
No events
Classes redefined (0 events):
No events
Internal exceptions (2 events):
Event: 0.039 Thread 0x000000010010b800 Exception <a 'java/lang/NoSuchMethodError': Method sun.misc.Unsafe.defineClass(Ljava/lang/String;[BII)Ljava/lang/Class; name or signature does not match> (0x00000005d5707cd8) thrown at [/HUDSON/workspace/8-2-build-solaris-sparcv9/jdk8u201/12322/hotspot/sr
Event: 0.039 Thread 0x000000010010b800 Exception <a 'java/lang/NoSuchMethodError': Method sun.misc.Unsafe.prefetchRead(Ljava/lang/Object;J)V name or signature does not match> (0x00000005d5707fc0) thrown at [/HUDSON/workspace/8-2-build-solaris-sparcv9/jdk8u201/12322/hotspot/src/share/vm/prims/j
jvm 内存映射
Dynamic libraries:
0x0000000100000000 /usr/jdk/instances/jdk1.8.0_201/bin/jstack
0x00007fffedd00000 /usr/jdk/instances/jdk1.8.0_201/bin/../lib/sparcv9/jli/libjli.so
0x00007ffffcffc000 /lib/64/libthread.so.1
0x00007ffffcffa000 /lib/64/libdl.so.1
0x00007ffffef00000 /lib/64/libc.so.1
0x00007ffff3500000 /usr/jdk/instances/jdk1.8.0_201/jre/lib/sparcv9/server/libjvm.so
0x00007ffffcff6000 /lib/64/libsocket.so.1
0x00007ffffcff4000 /usr/lib/64/libsched.so.1
0x00007ffff6a00000 /lib/64/libm.so.1
0x00007ffff6800000 /usr/lib/64/libCrun.so.1
0x00007ffffcff2000 /lib/64/libdoor.so.1
0x00007ffff6600000 /usr/lib/64/libdemangle.so.1
0x00007ffff6400000 /lib/64/libkstat.so.1
0x00007ffffce00000 /lib/64/libm.so.2
0x00007ffff3300000 /usr/jdk/instances/jdk1.8.0_201/jre/lib/sparcv9/libverify.so
0x00007ffff3100000 /usr/jdk/instances/jdk1.8.0_201/jre/lib/sparcv9/libjava.so
0x00007ffffcfe4000 /lib/64/libnsl.so.1
0x00007ffff5e00000 /lib/64/libscf.so.1
0x00007ffff5c00000 /lib/64/libuutil.so.1
0x00007ffff5a00000 /lib/64/libgen.so.1
0x00007ffff5800000 /lib/64/libnvpair.so.1
0x00007ffff5600000 /usr/lib/64/libv12n.so.1
0x00007ffff5400000 /lib/64/libcmdutils.so.1
0x00007ffff5200000 /lib/64/libuuid.so.1
0x00007ffff5000000 /lib/64/libavl.so.1
0x00007ffff4e00000 /lib/64/libcontract.so.1
0x00007ffff4c00000 /lib/64/libinetutil.so.1
0x00007ffff2f00000 /usr/jdk/instances/jdk1.8.0_201/jre/lib
jvm 启动参数
VM Arguments:
jvm_args: -Dapplication.home=/usr/jdk/instances/jdk1.8.0_201 -Xms8m -Dsun.jvm.hotspot.debugger.useProcDebugger -Dsun.jvm.hotspot.debugger.useWindbgDebugger
java_command: sun.tools.jstack.JStack java core
java_class_path (initial): /usr/jdk/instances/jdk1.8.0_201/lib/tools.jar:/usr/jdk/instances/jdk1.8.0_201/lib/sa-jdi.jar:/usr/jdk/instances/jdk1.8.0_201/classes
Launcher Type: SUN_STANDARD
其他例子:
五.栈溢出引起的Crash
Java代码引起的栈溢出,通常不会引起JVM的Crash,而是抛出一个Java异常:java.lang.StackOverflowError。但是在Java虚拟机中,Java的代码和本地C或C++代码公用相同的Stack。这样,在执行本地代码所造成的栈溢出,就有可能引起JVM的Crash了。栈溢出引起的Crash会在日志的文件头中看到“EXCEPTION_STACK_OVERFLOW”字样。另外,在当前线程的Stack信息中也能发现一些信息。例如下面的例子:
- -----------------------------------------------------------------------------------
- # An unexpected error has been detected by HotSpot Virtual Machine:
- #
- # EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x10001011, pid=296, tid=2940
- #
- # Java VM: Java HotSpot(TM) Client VM (1.6-internal mixed mode, sharing)
- # Problematic frame:
- # C [App.dll+0x1011]
- #
- --------------- T H R E A D ---------------
- Current thread (0x000367c0): JavaThread "main" [_thread_in_native, id=2940]
- :
- Stack: [0x00040000,0x00080000), sp=0x00041000, free space=4k
- Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
- C [App.dll+0x1011]
- C [App.dll+0x1020]
- C [App.dll+0x1020]
- :
- C [App.dll+0x1020]
- C [App.dll+0x1020]
- ......
- Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
- j Test.foo()V+0
- j Test.main([Ljava/lang/String;)V+0
- v ~StubRoutines::call_stub
- --------------------------------------------------------------------------------
在上面的信息中,可以发现这是个栈溢出的错误。并且当前栈剩余的空间已经很小了(free space =4k)。
因此建议将JVM的Stack的尺寸调大,主要设计两个参数:“-Xss” 和“-XX:StackShadowPages=n”。但是,将栈的尺寸调大,也意味着在有限的内存资源中,能打开的最大线程数会减少。
四.内存回收引起的Crash
内存回收引起的Crash有以下的特点:在日志文件头一般有“ EXCEPTION_ACCESS _VIOLATION”和
“# Problematic frame: # V [jvm.dll+....”的信息,意味着这是在JVM内部处理,而且多半是JVM的Bug。
(**********看到这里我们知道我报错时意味着这是在JVM内部处理,而且多半是JVM的Bug*********)
对于这类问题,最快的方法就是绕过它。
另外,在Thread的DUMP信息最后,还能看到有关内存回收的行为例如:
- --------------- T H R E A D ---------------
- Current thread (0x00a56668): VMThread [id=4360]
- siginfo: ExceptionCode=0xc0000005, reading address 0x00000057
- Registers:
- ........
- Stack: [0x03cf0000,0x03d30000), sp=0x03d2fc18, free space=255k
- Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
- V [jvm.dll+0x15e87e]
- VM_Operation (0x063efbac): full generation collection, mode: safepoint, requested by thread 0x040f83f8
- ------------------------------------------------------------
可以清楚的看到JVM正在做 “full generation collection”。另外还有可能看到,其他的回收行为:
对于内存回收的错误,一般
- generation collection for allocation
- full generation collection
- parallel gc failed allocation
- parallel gc failed permanent allocation
- parallel gc system gc
- (***********这些错,俺都没碰到***********)
采取改变回收的算法和参数的方法来绕过去。例如,来自客户的日志除了上面的日志信息,在日志中Heap信息中还能发现一些其他信息:
- --------------------------------------------------------------
- Heap
- def new generation total 22592K, used 19530K [0x10010000, 0x11890000, 0x138f0000)
- eden space 20096K, 97% used [0x10010000, 0x11322bd8, 0x113b0000)
- from space 2496K, 0% used [0x113b0000, 0x113b0000, 0x11620000)
- to space 2496K, 0% used [0x11620000, 0x11620000, 0x11890000)
- tenured generation total 190696K, used 100019K [0x138f0000, 0x1f32a000, 0x30010000)
- the space 190696K, 52% used [0x138f0000, 0x19a9cf38, 0x19a9d000, 0x1f32a000)
- compacting perm gen total 38656K, used 38588K [0x30010000, 0x325d0000, 0x34010000)
- the space 38656K, 99% used [0x30010000, 0x325bf038, 0x325bf200, 0x325d0000)
- ----------------------------------------------------------------
上面的信息能看出在Crash的时候,JVM的PermSize空间几乎已经消耗完了,并且回收算法在压缩Perm空间的时候出了错。因此,建议改变内存回收的算法,或扩大PermSize和MaxPermSize的数值。
(*******这个倒是可以尝试*******)