由于Linux RAM磁盘缓存未释放而导致Java OutOfMemoryError

时间:2010-05-21 13:48:46

标签: java linux memory linux-kernel

整个过程将运行良好,然后,bam,在没有警告的情况下,它会抛出此错误。有时似乎在无所事事的中间。它将在白天看似随机的时间发生。我检查了机器上是否还有其他东西在运行,比如预定的备份或什么,但什么也没找到。该机器具有足够的物理内存(2GB,大约1GB可用于3-500MB负载),并且具有足够的-Xmx指定。

根据我们的系统管理员,问题是当JVM需要分配内存时,内核用作磁盘缓存的RAM(显然只有8MB)不会被释放,因此JVM进程会抛出OutOfMemoryError。这可能是因为Java在分配之前询问内核是否有足够的内存,并发现它不足,导致崩溃。

但是,我想,Java只是试图通过内核分配内存,当内核得到这样的请求时,它会通过抛出一些磁盘缓存为应用程序腾出空间。

有没有其他人遇到过这个问题,如果有,那么错误是什么,你是如何解决的? 我们目前在VMWare ESX中的SLES 10 SP2 Linux 2.6.16.60-0.42.9-smp上使用jdk1.6.0_20。

2 个答案:

答案 0 :(得分:2)

  

根据我们的系统管理员,问题是当JVM需要分配内存时,内核用作磁盘缓存的RAM(显然只有8MB)不会被释放,因此JVM进程会抛出OutOfMemoryError。

我认为你的系统管理员出错了。 Linux将自动且透明地增加和缩小缓冲区缓存的大小,具体取决于系统对运行进程的物理内存的需求。如果没有,那么您的操作系统会严重破坏。

您的Java应用程序更可能发生内存泄漏,导致其使用不断增加的堆空间量。最终你运行-Xmx限制并获得一个OOME。我将通过在启用GC日志的情况下运行应用程序来开始调查此问题。这将告诉您堆如何随着时间的推移而增长,GC回收的空间等等。

另一种可能性是您没有配置足够的交换空间。

答案 1 :(得分:1)

你知道在抛出异常时java分配了多少内存吗?问题可能是Java使用了-Xmx指定的所有内存。 (请记住,-Mmx给出了允许的最大内存使用量,因此如果使用量增长超过指定的大小,java将抛出OutOfMemmoryException,即使linux内核能够提供更多的内存)。

但是为了找出是否是这种情况,尝试给它一个等于-Xms指定大小的-Xms。 (-Ms设置初始大小,java应该更新,因此它会在启动时分配所有需要的内存)。

如果java仍然启动,并且仍然给你OutOfMemoryException,那么问题很可能是你的-Mx很小。

ps:我很确定内存分配不会因正常的Linux内核而失败,因为内核过度使用,所以如果整个系统真的内存不足,就会出现页面错误(而且oom killer,会杀死一个任务)而不是java异常。但java可能会使用一些特殊功能来分配内存,所以我不确定这是否适用于此。