Java是否使用JNI"开箱即用"?

时间:2017-12-18 02:42:00

标签: java java-native-interface native

在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?
  3. 任何Java API实现都需要系统调用,因此如果我更正,似乎没有避免与本机代码的接口。

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

2 个答案:

答案 0 :(得分:4)

  
      
  1. 在本地使用JNI时,不要标记为此类的方法吗?
  2.   

是的,这就是它的含义。

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

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

对于应用程序,使用JNI是可选的这对于JVM来说是必不可少的。

答案 1 :(得分:3)

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

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

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

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

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

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

简而言之,尽管JVM确实使用了JNI,但这并不是不加区别地为自己的类使用JNI的借口。