如何在 Java 中使用 posix_spawn()
我继承了一个旧应用程序,该应用程序使用 ProcessBuilder.start()
在 Solaris 10 服务器上执行脚本。
不幸的是,此脚本调用由于内存问题而失败,如此处所述
Oracle 建议使用 posix_spawn()
,因为 ProcessBuilder.start()
在幕后使用 fork/exec
。
我一直无法找到任何
在 Java 中使用 posix_spawn()
的示例(例如,如何调用 "myScript.sh"
),甚至找不到所需的包。
您能给我举一个关于如何在 Java 中使用 posix_spawn() 的简单示例吗?
I've inherited a legacy application that uses ProcessBuilder.start()
to execute a script on a Solaris 10 server.
Unfortunately, this script call fails due to a memory issue, as documented here
Oracle's recommendation is to use posix_spawn()
since, under the covers, ProcessBuilder.start()
is using fork/exec
.
I have been unable to find any examples (e.g., how to call "myScript.sh"
)
using posix_spawn()
in Java, or even what are the packages that are required.
Could you please, point me to a simple example on how to use posix_spawn()
in Java?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
最新版本的 Java 7 和 8 在内部支持
posix_spawn
。命令行选项
或在运行时启用
我有点困惑哪些 Java 版本/操作系统组合默认启用了此选项,但我确信您可以快速测试并找出设置此选项是否会产生影响。
作为参考,要返回到旧的
fork
方法,只需使用来证明您的 JVM 版本使用中是否遵循此选项,
并且下次
exec
时您将收到错误。这样您就知道 JVM 正在接收此选项。Recent version of Java 7 and 8 support
posix_spawn
internally.command line option
or enable at runtime
I'm a little confused as to which Java version/OS combinations have this enabled by default, but I'm sure you could test and find out pretty quickly whether setting this option makes a difference.
For reference, to go back to the old
fork
method simply useTo prove whether this option is respected in your JVM version use
and you will get an error next time you
exec
. This way you know the JVM is receiving this option.另一种不需要 JNI 的替代方法是创建一个单独的“进程生成器”应用程序。我可能会让这个应用程序公开一个 RMI 接口,并创建一个包装对象来替代 ProcessBuilder。
您可能还需要考虑让这个“spawner”应用程序启动您的旧应用程序。
An alternative, which does not require JNI, is to create a separate "process spawner" application. I would probably have this application expose an RMI interface, and create a wrapper object that is a drop-in replacement for
ProcessBuilder
.You might also want to consider having this "spawner" application be the thing that starts your legacy application.
您需要先熟悉 JNI 。了解如何从 Java 代码调用本机例程。一旦你这样做了 - 你可以查看这个示例,看看它是否有帮助你的问题。您特别感兴趣的是:
You will need to familiarize yourself with JNI first. Learn how to call out into a native routine from Java code. Once you do - you can look at this example and see if it helps with your issue. Of particular interest to you is:
一个更简单的解决方案是保持代码不变,只需向服务器添加更多虚拟内存即可。
即:
编辑:澄清一下,问题中的链接现在已损坏:
问题是由于 JVM 被分叉而导致系统虚拟内存不足。例如,假设 JVM 使用 2 GB 的 VM,则需要额外 2 GB 的 VM 才能在 Solaris 上成功派生。这里不涉及分页,只是内存预留。与默认情况下过度使用内存的 Linux 内核不同,Solaris 确保分配的内存由 RAM 或交换区支持。由于没有足够的可用交换空间,分叉失败。扩大交换可以使分叉成功,而不会对性能产生任何影响。就在分叉之后,exec“取消保留”这 2GB RAM 并恢复到与 posix_spawn 相同的情况。
另请参阅此页面,了解有关内存分配的说明Solaris 和其他操作系统。
A much simpler solution would be to keep your code unchanged and simply add more virtual memory to your server.
i.e.:
Edit: To clarify as the link present in the question is now broken:
the question is about a system out of virtual memory due to the JVM being forked. Eg, assuming the JVM uses 2 GB of VM, an extra 2 GB of VM is required for the fork to succeed on Solaris. There is no pagination involved here, just memory reservation. Unlike the Linux kernel which by default overcommits memory, Solaris makes sure allocated memory is backed by either RAM or swap. As there is not enough swap available, fork is failing. Enlarging the swap allows the fork to succeed without any performance impact. Just after the fork, the exec "unreserves" this 2GB of RAM and revert to a situation identical to the posix_spawn one.
See also this page for an explanation about memory allocation under Solaris and other OSes.