我继承了使用ProcessBuilder.start()
在Solaris 10服务器上执行脚本的遗留应用程序。
不幸的是,由于内存问题,此脚本调用失败,如文档here
所示 Oracle的建议是使用posix_spawn()
,因为ProcessBuilder.start()
使用fork/exec
。
我无法找到任何示例(例如,如何调用"myScript.sh"
)
在Java中使用posix_spawn()
,甚至是所需的包。
请问,请给我一个关于如何在Java中使用posix_spawn()
的简单示例?
答案 0 :(得分:3)
另一种不需要JNI的方法是创建一个单独的“进程生成器”应用程序。我可能会让这个应用程序公开一个RMI接口,并创建一个包装器对象,它是ProcessBuilder
的替代品。
您可能还想考虑让这个“spawner”应用程序成为启动旧应用程序的东西。
答案 1 :(得分:2)
您首先需要熟悉JNI。学习如何从Java代码调用本机例程。完成后 - 您可以查看this示例,看看它是否有助于解决您的问题。你特别感兴趣的是:
if( (RC=posix_spawn(&pid, spawnedArgs[0], NULL, NULL, spawnedArgs, NULL)) !=0 ){
printf("Error while executing posix_spawn(), Return code from posix_spawn()=%d",RC);
}
答案 2 :(得分:1)
更简单的解决方案是保持代码不变,只需向服务器添加更多虚拟内存。
即:
mkfile 2g /somewhere/swap-1
swap -a /somewhere/swap-1
编辑:澄清问题中的链接现在已被破坏:
问题是由于JVM被分叉而导致虚拟内存系统出现问题。例如,假设JVM使用2 GB的VM,则fork需要额外的2 GB VM才能在Solaris上成功运行。这里没有涉及分页,只是内存预留。与默认情况下过度使用内存的Linux内核不同,Solaris确保分配的内存由RAM或交换支持。由于没有足够的可用交换,fork失败了。扩展交换允许fork成功而不会对性能产生任何影响。在fork之后,exec“取消”这个2GB的RAM并恢复到与posix_spawn相同的情况。
有关Solaris和其他操作系统下的内存分配的说明,另请参阅此page。
答案 3 :(得分:1)
最新版本的Java 7和8在内部支持posix_spawn
。
命令行选项
-Djdk.lang.Process.launchMechanism=POSIX_SPAWN
或在运行时启用
System.setProperty("jdk.lang.Process.launchMechanism", "POSIX_SPAWN");
我很遗憾默认情况下启用了哪个Java版本/操作系统组合,但我确定您可以快速测试并快速找到设置此选项是否有所作为。
作为参考,要返回旧fork
方法,只需使用
-Djdk.lang.Process.launchMechanism=fork
要证明在JVM版本中是否遵守此选项,请使用
-Djdk.lang.Process.launchMechanism=dummy
您下次exec
时会收到错误消息。这样您就知道JVM正在接收此选项。