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

社区

picture.image

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):方法区的一部分,存放编译器生成的各种字面值和符号引用。

picture.image

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 就可能破坏整个应用程序。

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
如何利用云原生构建 AIGC 业务基石
AIGC即AI Generated Content,是指利用人工智能技术来生成内容,AIGC也被认为是继UGC、PGC之后的新型内容生产方式,AI绘画、AI写作等都属于AIGC的分支。而 AIGC 业务的部署也面临着异构资源管理、机器学习流程管理等问题,本次分享将和大家分享如何使用云原生技术构建 AIGC 业务。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论