1

我正在编写一个需要调用不安全本机代码的 Windows Java 应用程序,并且我需要防止此代码访问 Java 对象和 JVM 数据结构,否则它可能会使 JVM 崩溃或侵入敏感数据。在你问之前,这个本机代码已经过验证——它只能调用几个 API,不能有某些指令,所以我们知道它不会 VirtualProtect 本身或其他内存区域来获得更多的访问权限和乱七八糟的东西。

无论如何,我的第一次尝试是将此代码包装到一个单独的进程(沙箱)中,并使用 IPC 与 Java 对话。有一个 JNI DLL 在 Java 端执行 IPC 工作。基本上,每次我们需要运行不安全的本机代码时,我们的 Java 应用程序都会调用一个 JNI 函数,该函数使用自动重置 Windows 事件唤醒沙箱,然后等待完成。沙盒运行不安全的本机代码并使用另一个自动重置 Windows 事件唤醒 JVM,然后生活继续。如果不是那么慢就完美了。

问题是不安全的本机代码可能包含一些执行非常快速的计算的函数,并且可以从 Java 调用数百万次,因此调用开销应该是最小的。但是这种开销是巨大的,因为 JVM 通过 Windows 事件唤醒沙箱,当沙箱返回时反之亦然。这个过程是进程内(非 IPC)解决方案的 8 倍,其中不安全的本机代码包装在 JNI DLL 中(因此调用发生在同一个线程中,在同一个时间片中)。

我的第一个猜测是,当 JVM 唤醒沙箱时,Windows 只将沙箱线程置于就绪集,因此它仅在几毫秒后运行。当沙盒返回时也会发生同样的情况。不算两个(可能很昂贵)上下文切换。

此处的Microsoft 文档说明如下:

如果较高优先级的线程可以运行,系统将停止执行较低优先级的线程(不允许其完成使用其时间片),并将完整的时间片分配给较高优先级的线程。

为了测试这个理论,我将 THREAD_PRIORITY_TIME_CRITICAL 分配给沙盒线程。有一些收获。性能从进程中(非 IPC)解决方案的 8 倍提高到 5 倍。但我需要更多,否则这个 Java 应用程序可能无法投入生产!

您可以通过两种方式帮助我:

  • 告诉我是否有更快的方法来唤醒另一个进程,例如强制上下文切换或执行进程间过程调用。

  • 告诉我如何在进程内运行不安全的本机代码时保护 JVM。我听说 Google Native Client 会这样做,但我只找到了这个文档。如果您了解更多,请提供有关如何实施的更详细信息的链接。

4

1 回答 1

0

我通过在通过文件映射从 JVM 访问的共享内存变量上使用自旋锁执行 JVM 沙盒交互来解决了这个问题。这个问题解释了如何在 C++ 环境中实现。使用 .移植到 Java 很容易。MappedByteBuffer

于 2013-11-20T21:43:07.817 回答