在我们的工作中,一个目标平台是运行Linux的资源受限小型服务器(内核2.6.13,基于旧版Fedora Core的自定义发行版)。该应用程序使用Java编写(Sun JDK 1.6_04)。当内存使用量超过160MB时,Linux OOM killer被配置为杀死进程。即使在高负载下,我们的应用程序也从未超过120MB,加上一些其他活动的本地进程,我们仍然远低于OOM限制。
然而,事实证明,Java Runtime.getRuntime().exec()方法(从Java执行外部进程的标准方式)在Linux上具有特别不幸的实现,因为生成的子进程会(暂时)需要与父进程相同数量的内存,因为地址空间被复制。结果是,我们的应用程序在进行Runtime.getRuntime().exec()操作后很快就被OOM killer杀死了。
我们目前通过拥有一个单独的本地程序执行所有外部命令并通过套接字与该程序通信来解决此问题。但这不是最理想的。
在在线发布此问题后,我得到了一些反馈,表明在“更新”的Linux版本上不应该发生这种情况,因为它们使用copy-on-write实现posix fork() 方法,可能意味着只有在需要修改时才会立即复制整个地址空间的页面。
我的问题是:
- 这是真的吗?
- 这是内核、libc实现或完全其他地方的东西吗?
- 从哪个内核/libc/任何东西的版本开始可用fork()的copy-on-write?