2

我正在尝试寻找不使用 fork 的 Java Runtime.exec() 替代方案。问题是我们的 JVM 消耗了大部分内存,并且该进程上的 Runtime.exec 分叉可能会导致内存问题,即使是写入时复制和过度使用(这在 stackoverflow 中经常讨论,请参阅Java Runtime.getRuntime().exec () 替代品)。

在另一个 stackoverflow 帖子中,提出了使用 JNA 的解决方案,但是没有对此解决方案的评论,并且评价不高:如何解决“java.io.IOException:错误= 12,无法分配内存”调用 Runtime#exec( )?

同样,这里提出了类似的 JNA 解决方案:http: //sanjitmohanty.wordpress.com/2011/12/20/overcoming-runtime-exec-havoc-with-jna/

我的问题是:使用 JNA 进行系统调用是否会阻止分叉,是否避免了分叉可能导致的后续内存分配问题?这是我正在使用的代码:

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");
 }
4

4 回答 4

3

system不需要做一个fork(或同等的),而 JNA 对此无能为力。

我不认为人们建议您使用 JNA 来调用system,而是建议您进行实际的系统调用。例如,该博客给出chmodchown作为示例。因此,使用您的示例,而不是使用 JNA 来调用system('ls'),调用opendirreaddir(当然,这同样适用于您真正调用的任何内容)。

您可能必须制作一个 DLL 来包装所需的功能。

于 2012-05-24T00:24:24.913 回答
3

可能不是。您正在调用的实现system()几乎肯定是在使用fork()它自己——C 实现看起来像:

int system(const char *cmd) {
    if (fork() == 0) {
        execl("/bin/sh", "-c", cmd);
        _exit(1);
    }
    int result;
    wait(&result);
    return WEXITSTATUS(result);
}

一个更可行的解决方案是保持与一个小型外部进程的通信线路(例如管道),该进程可以为您生成子进程。Android 做了很多类似的事情;外部过程称为“合子”。

于 2012-05-24T00:26:42.207 回答
1

没有 fork() 就不可能执行“系统”。

于 2012-05-24T00:24:49.677 回答
0

那么 system() 是如何工作的呢?如果它还在使用叉子?我遇到了这个错误“java.io.IOException:error = 12,无法分配内存”的问题,这为我解决了这个问题:

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);
    }
于 2013-12-26T10:04:26.503 回答