Walt You - 行是知之始

《Effective Java》学习日志(八)66:谨慎地使用本地方法

2018-12-27


学习资料主要参考: 《Effective Java Third Edition》,作者:Joshua Bloch



Java Native Interface(JNI)允许Java程序调用本地方法,这些方法是用本地编程语言(如C或C ++)编写的方法。

从历史上看,本地方法有三个主要用途。

  1. 它们提供对特定于平台的设施(如注册管理机构)的访问。
  2. 它们提供对现有本地代码库的访问,包括提供对旧数据的访问的旧库。
  3. 最后,本地方法用于以本地语言编写应用程序的性能关键部分,以提高性能。

使用本地方法访问特定于平台的工具是合法的,但很少需要:随着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是合理的。

使用本地方法具有严重的缺点。

  1. 由于本地语言不安全(第50项),使用本地方法的应用程序不再免受内存损坏错误的影响。
  2. 由于本地语言比Java更依赖于平台,因此使用本地方法的程序不太可移植。 它们也更难调试。 如果您不小心,原生方法可能会降低性能,因为垃圾收集器无法自动化甚至跟踪本地内存使用情况(第8项),并且存在与进出本地代码相关的成本。
  3. 最后,本地方法需要“粘合代码”,难以阅读和编写繁琐。

总之,在使用本地方法之前要三思而后行。 您很少需要使用它们来提高性能。 如果必须使用本地方法来访问低级资源或本地库,请尽可能少地使用本地代码并对其进行全面测试。 本地代码中的单个错误可能会破坏整个应用程序。


Content