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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java是否使用JNI“开箱即用”?相关的知识,希望对你有一定的参考价值。

关于Java何时使用JNI,我在概念上并不清楚。文献1,2似乎建议使用JNI是可选的 - 它对我自己的现有本地C应用程序来说是一个有用的功能,但是在可能的情况下避免使用它是一个好习惯:Liang表示“记住,一旦应用程序使用JNI ,它有可能失去[便携性和安全性]的两个好处“。

但是,我在SDK中查看了Oracle的API实现,我在public static native void arraycopy中看到了java/lang/System.java。问题:

  1. 在本地使用JNI时,不标记为这样的方法吗?
  2. Java在进行系统调用时是否使用JNI?

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

1:Horstmann,核心Java第2卷 2. Liang,Java™Native Interface程序员指南和规范

答案
  1. 在本地使用JNI时,不标记为这样的方法吗?

是的,这就是它的含义。

  1. Java在进行系统调用时是否使用JNI?

同样的问题真的。只有本机方法才能调用系统调用,因此Java代码只能通过本机方法调用系统调用。

对于应用程序,使用JNI是可选的。这对JVM至关重要。

另一答案

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

正如other answer中详述的那样,JVM确实依赖于JNI。但这不是一个完整的答案。

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

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

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

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

简而言之,即使JVM确实使用JNI,这也不是不加区别地为您自己的类使用JNI的借口。

以上是关于Java是否使用JNI“开箱即用”?的主要内容,如果未能解决你的问题,请参考以下文章

Java技术jQuery自定义插件开发实践

基于SSM源代码风格Java代码生成器 Maven版开箱即用 摸鱼神器

Structuremap 是不是支持开箱即用的 Lazy?

使用开箱即用的 SPDY 运行 Jetty

Windows Qt 二进制安装程序是不是支持开箱即用的 DBus?

是否有一种开箱即用的方法来反序列化 Json.Net 中的抽象类?