Java 是否“开箱即用”地使用 JNI?

flo*_*w2k 3 java java-native-interface native

我在概念上并不清楚 Java 何时使用 JNI。文献1,2似乎建议使用 JNI 是可选的 - 它对于我自己现有的本机 C 应用程序来说是一个有用的功能,但最好尽可能避免使用它:\nLiang 指出“记住,一旦应用程序使用JNI,它可能会失去[可移植性和安全性]的两个好处”。

\n\n

然而,我在 SDK 中查看了 Oracle 的 API 实现,我public static native void arraycopyjava/lang/System.java. 问题:

\n\n
    \n
  1. 在本机中,标记为这样的方法不使用 JNI 吗?
  2. \n
  3. Java在进行系统调用时不使用JNI吗?
  4. \n
\n\n

任何 Java API 实现都需要系统调用,所以如果我是正确的,似乎无法避免与本机代码的交互。

\n\n

1:Horstmann,核心 Java 第 2 卷
\n2。梁,Java\xe2\x84\xa2 Native Interface Programmer\xe2\x80\x99s 指南和规范

\n

Ale*_*ohn 5

您列出了 JNI 的两个缺点——可移植性安全性。实际上,还有另外一个,在日常生活中更重要:JNI 调用会带来显着的性能成本,因为它们会影响全局 JVM 状态并锁定一些 JVM 功能,包括 GC。

正如另一个答案中详细介绍的,JVM 确实依赖于 JNI。但这并不是一个完整的答案。

您的 JVM 可能支持快速 JNI 方法(例如 Android ART 就支持)。这些方法保证快速且无阻塞,并且可以在不更改状态的情况下执行它们,请参见@FastNative。Java SDK 本机方法大量使用此类改进,因此它们不会遭受传统 JNI 的性能成本。

这些本机方法在运行期间不依赖LoadLibrary()。这消除了 JNI 的另一个显着性能成本 - 在运行时加载和“绑定”本机方法。运行时绑定的最大风险是它在由类加载器确定的任意时间发生,并且可能与 JVM 或应用程序当时必须执行的其他紧急操作发生冲突。与系统本机方法无关。

此外,可移植性问题也无关紧要:Java 运行时是为每个受支持的平台精心设计的,它本身并不是“可移植的”,只有在其之上运行的 Java 应用程序才是“可移植的”。

最后, JNI 的安全风险是双重的:JNI 不受私有声明的限制,并且本机代码可能会执行危险的操作,危及在同一 JVM 中运行的任何类或应用程序。而且,从第三方库加载时,JNI 代码可能会被黑客攻击(例如,更改操作系统环境就足以导致System.loadLibrary()加载欺诈者版本的库)。系统本机方法不会受到此类攻击。

简而言之,即使 JVM 确实使用了 JNI,但这也不能成为你自己的类不加区别地使用 JNI 的借口。