应用环境发生了内存溢出之后应用竟然没停止服务,可能么

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问题,大家一般怎么来进行分析与定位的?
Global site tag (gtag.js) - Google Analytics