学习资料主要参考: 《Effective Java Third Edition》,作者:Joshua Bloch
Java Native Interface(JNI)允许Java程序调用本地方法,这些方法是用本地编程语言(如C或C ++)编写的方法。
从历史上看,本地方法有三个主要用途。
- 它们提供对特定于平台的设施(如注册管理机构)的访问。
- 它们提供对现有本地代码库的访问,包括提供对旧数据的访问的旧库。
- 最后,本地方法用于以本地语言编写应用程序的性能关键部分,以提高性能。
使用本地方法访问特定于平台的工具是合法的,但很少需要:随着Java平台的成熟,它提供了对以前仅在主机平台中发现的许多功能的访问。 例如,Java 9中添加的流程API提供对OS流程的访问。 当Java中没有可用的等效库时,使用本地方法来使用本地库也是合法的。
通常不建议使用本地方法来提高性能。 在早期版本中(在Java 3之前),它通常是必要的,但从那时起JVM就变得更快了。 对于大多数任务,现在可以在Java中获得可比较的性能。 例如,当在版本1.1中添加java.math时,BigInteger依赖于用C编写的一个快速的多精度算术库。在Java 3中,BigInteger在Java中重新实现,并仔细调整到比本地实现运行速度更快的程度。
这个故事的一个令人遗憾的结论是BigInteger从那以后变化不大,除了Java 8中大数字的快速乘法。在那个时候,本地库继续快速工作,特别是GNU多精度算术库(GMP)。 现在需要真正高性能多精度算法的Java程序员通过本地方法[Blum14]使用GMP是合理的。
使用本地方法具有严重的缺点。
- 由于本地语言不安全(第50项),使用本地方法的应用程序不再免受内存损坏错误的影响。
- 由于本地语言比Java更依赖于平台,因此使用本地方法的程序不太可移植。 它们也更难调试。 如果您不小心,原生方法可能会降低性能,因为垃圾收集器无法自动化甚至跟踪本地内存使用情况(第8项),并且存在与进出本地代码相关的成本。
- 最后,本地方法需要“粘合代码”,难以阅读和编写繁琐。
总之,在使用本地方法之前要三思而后行。 您很少需要使用它们来提高性能。 如果必须使用本地方法来访问低级资源或本地库,请尽可能少地使用本地代码并对其进行全面测试。 本地代码中的单个错误可能会破坏整个应用程序。