【问题标题】:32bit JVM, ProcessBuilder.start() and ENOMEM32 位 JVM、ProcessBuilder.start() 和 ENOMEM
【发布时间】:2012-01-05 23:57:01
【问题描述】:

我必须处理的一个应用程序使用ProcessBuilder 定期启动 shell 帮助程序。由于不为人知的原因,它仍然在 32 位 JVM(Sun,1.6.0.25)上运行,即使底层操作系统是 64 位(RHEL 5.x 值得)。

这个应用程序是内存快乐的,所以堆大小设置为最大 3 GB,permgen 为 128M。

但是... 在随机时刻,shell 助手无法启动。不是因为 OutOfMemory,而是 ENOMEM……我能看到的唯一原因是地址空间不足。

好吧,当然,但与此同时,内存并没有真正承受压力,top 报告说 JVM 的实际内存使用量及其虚拟集大小甚至不到 3 GB...

看看Process 的代码可以看到什么,我看到核心方法被称为forkAndExec(),这几乎是不言自明的......根据我对这两个系统调用的了解,它应该'失败。但确实如此。并非总是如此。

为什么?

edit:需要注意的是使用了neo4j。好像经常使用FileChannel,会不会是地址空间不足的原因?

【问题讨论】:

  • 如果我没记错的话,当产生一个新进程时,Linux 最初会为新进程分配与父进程相同数量的内存。该分配立即调整为正确的大小。是否可能没有足够的可用内存来进行初始大小调整?我记得我们必须通过允许在操作系统中过度使用内存来解决这个问题。

标签: java fork processbuilder


【解决方案1】:

我会减小堆大小。实际使用的堆数量可能会导致分叉进程运行的空间越来越少(它从其父进程继承资源)

很可能只升级到 64 位 JVM 就可以解决问题,您可以尝试使用 Java 6 update 30 64 位来代替(只是看看它是否会解决问题)如果有或没有,它应该更多地说明原因是什么(然后你可以决定是否值得切换)

【讨论】:

  • 64 位在计划中...我绝对考虑过,我只是想知道为什么当前版本即使有一些可用的地址空间也不能分叉——或者不是?查看更新,我想我可能找到了原因
  • FileChannels 会占用文件资源,但不会占用太多地址空间。如果你有一个 32 位操作系统,你的 JVM 可能无法以 1.5 GB 的堆启动,所以你有一个 3 GB 的堆做得很好,你当然没有太多的虚拟空间可用。即使尝试 2.5 GB 堆也可能解决问题。
  • 我在想MappedByteBuffers:他们不占用堆空间...
  • 它们占用的堆空间不多(小于 1 KB),但它们当然使用虚拟内存。在 32 位进程中使用 MappedByteBuffers 听起来非常有限。比较你可以用 64 位 JVM 做什么vanillajava.blogspot.com/2011/12/…
  • 非常有趣...我不知道映射的大小是有限的。谢谢!
【解决方案2】:

我认为你被Linux memory overcommits killing your processes. 咬了,那篇博文建议了一个你可以调整的 sysctl 变量。

【讨论】:

  • 嗯,不,日志没有显示 OOM 杀手被触发......这似乎是 fork 系统调用在这里返回 ENOMEM
猜你喜欢
  • 2012-09-19
  • 2011-12-25
  • 2013-09-16
  • 2011-06-26
  • 1970-01-01
  • 2011-12-12
  • 2011-09-04
  • 2016-03-07
  • 2012-03-17
相关资源
最近更新 更多