应用环境发生了内存溢出之后应用竟然没停止服务,可能么
fxl545826
2013-10-27
服务器是 Redhat ,使用了 Tomcat 6 和 1.6的jdk,java -version的信息如下:
java version "1.6.0_26" Java(TM) SE Runtime Environment (build 1.6.0_26-b03) Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode) 因为配置了-XX:+HeapDumpOnOutOfMemoryError,所以应用会在日志出现: 2164562 [Unloading class sun.reflect.GeneratedMethodAccessor599] 2164563 java.lang.OutOfMemoryError: Java heap space 2164564 Dumping heap to java_pid29907.hprof ... 然后应用也没任何重启操作,后边继续提供服务,好似好奇怪的样子,不太符合常理啊。这个可以解释么? |
|
RednaxelaFX
2013-10-27
当然可能,而且很正常。OutOfMemoryError是可以catch的异常,catch了之后不选择忽略它的话程序就继续跑了呗。
|
|
fxl545826
2013-10-27
这个异常一般不都是JVM报的么?如果应用代码没任何这个try catch的话也可能会这样么?
如果是jvm在使用给对象分配内存的时候抛出的话,肯定是内存不够抛异常了,内存分配不到应用应该没法搞了吧? |
|
RednaxelaFX
2013-10-27
fxl545826 写道 这个异常一般不都是JVM报的么?
是JVM抛的,但照样可以catch。 fxl545826 写道 如果应用代码没任何这个try catch的话也可能会这样么?
要看如何界定“应用”。其实很多Web服务器都有自己安装uncaught exception handler,而它可以捕获到OutOfMemoryError,打日志,但不退出。从JVM的角度看这是“应用”的一部分,不过从你的角度看可能觉得这是“Web服务器”或者说“框架”的一部分,而不是你的应用的一部分。 fxl545826 写道 如果是jvm在使用给对象分配内存的时候抛出的话,肯定是内存不够抛异常了,内存分配不到应用应该没法搞了吧?
对啊,但OOME并不总是不可恢复的。例如说可能你的程序有bug,在触发bug的时候会尝试分配1GB大的数组,而当前剩余Java heap不足分配1GB内存,于是触发了OOME。这个OOME被捕获后忽略掉,程序继续跑,可能没再走到那个bug的路径里,没这种夸张的分配请求,于是程序又正常跑下去。这没啥奇怪的。 |
|
fxl545826
2013-10-27
2167507 Heap 2167508 PSYoungGen total 1170176K, used 43273K [0x00000007aaab0000, 0x0000000800000000, 0x0000000800000000) 2167509 eden space 1170112K, 3% used [0x00000007aaab0000,0x00000007ad4f2758,0x00000007f2160000) 2167510 from space 64K, 0% used [0x00000007f2160000,0x00000007f2160000,0x00000007f2170000) 2167511 to space 115776K, 0% used [0x00000007f8ef0000,0x00000007f8ef0000,0x0000000800000000) 2167512 PSOldGen total 2796224K, used 1290763K [0x0000000700000000, 0x00000007aaab0000, 0x00000007aaab0000) 2167513 object space 2796224K, 46% used [0x0000000700000000,0x000000074ec82fb8,0x00000007aaab0000) 2167514 PSPermGen total 262144K, used 118069K [0x00000006f0000000, 0x0000000700000000, 0x0000000700000000) 2167515 object space 262144K, 45% used [0x00000006f0000000,0x00000006f734d528,0x0000000700000000) 2167516 这个是内存dump的时候的日志,看起来好似都使用比较正常,大部分都占用率不到50%,可能有一个地方程序写的不合理,由于一个操作会出现如你所说类似的尝试分配一个1G或者更大的一个数组等类似对象。这个时候如果OOME的话看来也可能会如你所说,这个bug开发者可能本身自己try catch了Exception,然后走了catch,然后jvm又把不合理的对象回收掉,但是应用继续干他的活了。 |
|
blueyy617
2013-10-28
我之前也在64位机器下遇见过同样的情况,Tomcat6/JBoss加OpenJDK1.6/OpenJDK1.7的情形都用Loadrunner测试过,一旦部署在Tomcat6/JBoss上的Web应用需要调用Mysql数据库时,就会发生楼主遇到的这种情况:堆和非堆的内存使用都未满,就发生了Heap区的OOME。但是如果部署的应用不需要调用Mysql数据库,就不会发生这种不正常的情况。
|
|
fxl545826
2013-10-28
blueyy617 写道 我之前也在64位机器下遇见过同样的情况,Tomcat6/JBoss加OpenJDK1.6/OpenJDK1.7的情形都用Loadrunner测试过,一旦部署在Tomcat6/JBoss上的Web应用需要调用Mysql数据库时,就会发生楼主遇到的这种情况:堆和非堆的内存使用都未满,就发生了Heap区的OOME。但是如果部署的应用不需要调用Mysql数据库,就不会发生这种不正常的情况。
你解决了那个问题了么? |
|
blueyy617
2013-10-28
fxl545826 写道 你解决了那个问题了么?
还没有,只是粗浅的给问题定了下位,应该是WEB应用与MYSQL交互这方面的问题。 这貌似要涉及到WEB应用源码,但是换个WEB应用同样会出现这种情况,感觉又像是一个JDK共性的问题。 不知道你有没有在32位机器上做同样的测试?你会发现32位机器上又完全不会出现这种情况。感觉很是诡异 ![]() |
|
fxl545826
2013-10-28
我这边好似没遇到过这个问题,不过应该可能不是你想的那样吧?
|
|
blueyy617
2013-11-19
fxl545826 写道 我这边好似没遇到过这个问题,不过应该可能不是你想的那样吧?
确实不是这个原因,当时只是别人发现了这个问题,只是帮忙测试了一下。现在想想应该是R大说的那种类似的问题,因为记得那会用jstat -gccause指令查看时,第一次Full GC时的信息是“Allocation failed”,然后就接着OOM了,之后我就没有去跟进这个问题了,惭愧。不知道楼主现在这个问题有跟进没? 另外,感觉对于这种没有发生JVM Crash的OOM问题,大家一般怎么来进行分析与定位的? |