写点什么

Java 程序经验小结:谨慎的使用本地方法

发布于: 2021 年 01 月 10 日
Java程序经验小结:谨慎的使用本地方法

1、写在开头

JNI 全称 Java Native Interface。Java 本地方法接口,它允许 Java 应用程序可以调用本地方法(native method),本地方法就是指用本地程序设计语言(C/C++等)编写的特殊方法。

维基百科是这样解释的:“当应用无法完全用 Java 编程语言实现的时候,(例如,标准 Java 类库不支持的特定平台特性或者程序库时),JNI 使得编程者能够编写 native 方法来处理这种情况”。


开讲前,我们先回顾下 JVM 的基本结构。根据《Java 虚拟机规范(Java SE 7 版)》。

JVM 的内存管理包括以下几个运行时数据区域:

  • 程序计数器(Program Counter Register):当前线程执行的字节码指示器

  • Java 虚拟机栈(Java Virtual Machine Stacks):Java 方法执行的内存模型,每个方法会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。

  • 本地方法栈(Native Method Stack):(虚拟机使用到的)本地方法执行的内存模型。

  • Java 堆(Java Heap):虚拟机启动时创建的内存区域,唯一目的是存放对象实例,处于逻辑连续但物理不连续内存空间中。

  • 方法区(Method Area):存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

  • 运行时常量池(Runtime Constant Pool):方法区的一部分,存放编译器生成的各种字面值和符号引用。



2、本地方法的用途

本地方法主要提供三种用途:

  1. 提供“访问特定平台的机制”能力,如访问注册表(registry)和文件锁(file lock)

  2. 提供“访问遗留代码库”能力,进而访问遗留数据(legacy data)

  3. 编写应用程序中注重性能的部分,以提高系统的性能

使用本地方法访问特定于平台的机制是合法的。随着 JVM 的不断成熟,本地方法提供了越来越多以前只有在“宿主”平台才有的特性。例如,java 1.4 发行版新增的 java.util.prefs 包就提供了注册表的功能;1.6 发行版增加了 java.awt.SystemTray 提供了访问桌面系统托盘区的能力。

同时,使用本地方法来访问遗留代码也是合法的。


3、本地方法的重要性在下降

使用本地方法来提高性能的做法不值得提倡。早起的 jdk 发行版(1.3 之前),这样做法是必要的,但 JVM 实现变得越来越快了。对于大多数任务,现在即使不适应本地方法也能够获得与“使用本地方法”相当的性能了。

  • jdk 1.1 发行版增加了 java.math 时,BigInteger 是在一个用 C 编写的快速多精度运算库的基础上实现的。在当时,为了获取足够的性能,这样子做无可厚非

  • 在 jdk 1.3 之后,BigInteger 完全用 Java 重写了,并且进行了精心的性能调优


其二,C/C++编写的程序是非安全的。所以,使用了本地方法的应用程序也不可以避免受到内存毁坏导致的错误


Java 是一门安全的语言(safe language),因为它对于缓冲区、数组越界、非法指针以及其他的内存破坏错误都自动免疫,而类似内存溢出或者指针异常等问题却始终困扰着 C/C++这样的非安全语言。


其三,因为本地语言是平台相关,使用本地方法的应用程序也不再是“自由移植”的。

其四,使用了本地方法的应用程序使得代码调试变得困难,在进入和退出本地方法时,需要额外的固定开销。所以,如果本地方法只是做了少量工作,非但没有起到优化性能的目的,反而降低了性能。

其五,需要“胶合代码”的本地方法编写起来单调乏味,代码可读性也低


4、写在文末

如果你必须要使用本地方法来访问底层资源,或者遗留代码库,也要尽可能少用本地代码,并且进行全面测试。因为本地代码的一个 Bug 就可能破坏整个应用程序。


发布于: 2021 年 01 月 10 日阅读数: 47
用户头像

Diligence is the mother of success. 2018.03.28 加入

公众号:后台技术汇 笔者主要从事Java后台开发,喜欢技术交流与分享,保持饥渴,一起进步!

评论 (2 条评论)

发布
用户头像
写的挺好的
2021 年 03 月 03 日 19:21
回复
谢谢支持,希望对大家都有所帮助。
2021 年 03 月 05 日 09:11
回复
没有更多了
Java程序经验小结:谨慎的使用本地方法