OOM---Out of Memory
最让人头痛的问题之一。
我们系统上线算来已经有半年有余,从来没有出现过这样的问题。
但从上上个星期开始,就开始出现这个问题,当时只是作为了偶然性问题,将系统重启将之解决,没有提高认识高度,但从此造成损失就......
说说我们对此问题的认识和解决办法。
一般出现OOM问题,个人觉得应该从两个方面着手:应用程序和JVM的内存管理。
所以,一开始碰到此问题,首先反应的是我们系统应用程序造成的内存泄露。于是翻log,发现每次系统挂掉的时候调用的方法都不尽然一致,头痛了~~~
回想一下,从去年8月上线到现在从来没有出现过挂掉的情况,并且这次挂掉,之前并没有做过什么系统更新,所以,决定不从这方面入手。
那只剩下JVM的内存管理方面了。对于这方面问题
具体理论可以参考下网上的其他文章
比如:
http://wz.csdn.net/url/828071/
http://eric.moabc.net/diary/7358619
说说我的操作方案
1,考虑是不是真的Memory不够用了?增加JVM的Heap。 设置 -Xms2048m -Xmx2048m 。
32位的操作系统通常最大支持4G的内存寻址,而Linux一般为3G,Windows为2G
对此设置进行压力测试,发现结果同样让人郁闷,进程还是挂掉,于是第二天接着挨骂,还连累了前方的同学一起挨骂,那个悔啊~~~~~~
2,对于-Xss参数进行设置。
因为后台报错如下:
Exception in thread "CompilerThread1" java.lang.OutOfMemoryError: requested 32756 bytes for ChunkPool::allocate. Out of swap space?。
我的判断是在新的线程进入的时候已经没有了内存空间。
是不是我们给每个线程分配空间太大呢?
查阅相关资料
Xss:线程堆栈最大值。允许更多的虚拟内存空间地址被Java Heap使用。
默认值是-Xss512k
而sun公司的性能优化白皮书中提到的例子:
对于吞吐量的调优。机器配置:4G的内存,32个线程并发能力。
java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
-Xmx3800m -Xms3800m 配置了最大Java Heap来充分利用系统内存。
-Xmn2g 创建足够大的青年代(可以并行被回收)充分利用系统内存,防止将短期对象复制到老年代。
-Xss128 减少默认最大的线程栈大小,提供更多的处理虚拟内存地址空间被进程使用。
-XX:+UseParallelGC 采用并行垃圾收集器对年青代的内存进行收集,提高效率。
-XX:ParallelGCThreads=20 减少垃圾收集线程,默认是和服务器可支持的线程最大并发数相同,往往不需要配置到最大值。
由此可以看出对于这种用户读取还不是特别平凡,且并发数并不是很高的系统,可以将XSS设置低点,为了验证可靠性,我将一端设置成128k,另一端设置默认。
压力测试结果:
一小时过去了,压了128k多个请求,设置128k的没死!而另一端早在压到8k多请求的时候就死了。
将另一端端调整成128k,运行一天,两个服务都没出现挂掉的情况。
3,系统平稳运行一天,并不代表长久都可以平稳,所以必须找出原因。
从调整的配置看原因.
最有可能的原因是:线程分配内存太大占用了太多的Java Heap Memory,而照成了OOM问题
但是,还有一种原因:
OOM除了在JVM Heap不够时会发生,在Native Heap不够的时候也会发生,同时JVM Heap和Native Heap存在着相互影响和平衡的关系.Native Heap和 Java Heap大小配置是相互制约的,哪一部分分配多了都可能会影响到另外一部分的正常工作
我们给Xmx和Xms设置是2048m,也就是说给Native Heap空间不足1G了,是不是因为Native Heap空间造成的问题呢?
也不排除这种情况,但是此情况来不及验证。
调整至此,系统已经平稳运行了半月,再没有出现系统崩溃的情况,判断原因应该是因为资源分配不合理情况造成。