I am trying to find an alternative to Java Runtime.exec() that does not use a fork. The problem being that our JVM consumes most of the memory and a Runtime.exec fork on that process may cause memory problems, even with copy on write and overcomit (which has been often discussed in stackoverflow, see Java Runtime.getRuntime().exec() alternatives).
On another stackoverflow post, a solution was suggested using JNA, yet there were no comments on this solution and it was not highly rated: How to solve "java.io.IOException: error=12, Cannot allocate memory" calling Runtime#exec()?
Likewise a similar JNA solution was suggested here: http://sanjitmohanty.wordpress.com/2011/12/20/overcoming-runtime-exec-havoc-with-jna/
My question is: does using JNA to make a system call prevent a fork, and does it avoid the subsequent memory allocation problems that fork can cause? Here is the code I am using:
public class TestJNA {
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int system(String cmd);
}
private static int exec(String command) {
return CLibrary.INSTANCE.system(command);
}
public static void main(String[] args) {
exec("ls");
}
Probably not. The implementation of system()
that you're calling is almost certainly using fork()
itself -- the C implementation will look something like:
int system(const char *cmd) {
if (fork() == 0) {
execl("/bin/sh", "-c", cmd);
_exit(1);
}
int result;
wait(&result);
return WEXITSTATUS(result);
}
A more feasible solution would be to maintain lines of communication (e.g, pipes) to a small external process which can spawn off subprocesses for you. Android does something very much like this; the external process is known as the "zygote".