JNI学习笔记(二)——JNI

JNI 是JAVA Native Interface的简称,它是java平台的一个非常有用的特性。JNI 是java平台的一部分, 应用程序使用JNI,以便在java中调用“native code”(如C、C++语言写的代码)。



java平台和主机环境


java平台是一个编程环境,它包含java虚拟机(VM)和java应用程序编程接口(API)。java程序由java编程语言编写,并且被编译成与机器无关的二进制类的形式。一个类可以在任何VM上执行。API包含了一组预先定义好了的类。任何java平台的实现都要保支持java编程语言、java虚拟机以及java API。


长期的主机环境,需要主机操作系统、一组native库、和CPU指令集。native程序是用native编程语言写的(例如C、C++),被编译成特定主机的二进制代码,并且和native库一起被链接。native程序、native库通常依赖于特定的主机环境。


java平台通常被部署在一个主机环境的顶部。例如,JRE(java runtime environment)是一个在已有操作系统(solaris、windows等待)上支持java平台的SUN公司的产品。java平台提供了一组和下层主机环境无关的特性,以供java程序依赖、使用。



JNI的角色


有时候有必要允许java程序和native代码一起工作。开发人员不得不采用Java 平台来编译由传统的C、C++编写的程序。


JNI是一个强大的特性,它允许你利用java平台的优点,同时利用已经用其他语言写好了的代码。作为java VM的一部分,JNI有一个双向接口,以便允许java程序调用native代码,反之依然。

JNI是用来处理这种需要将java程序和native代码一起编译的情形的。作为ieyig双向接口,JNI可以支持native库和native程序。

1)可以用JNI写native方法,以便java程序调用实现在native库中的函数。java程序调用native方法和调用java方法的方式一样。

2)JNI支持一个能够将java VM嵌入到native程序中的调用接口。native程序可以和一个在java VM中实现native库进行链接,然后通过调用接口来执行用java编程语言写的软件组件。例如,一个用C写的浏览器可以在已经嵌入了的java VM执行已下载的小程序。



使用JNI的影响


应用程序使用了JNI,怎将失去java平台的两个优点:

1)依赖JNI的java程序将不容易在多个主机环境中执行。即便程序的用java语言编写的部分时候多主机环境中运行,但是它需要和native代码部分的程序重新编译,这将导致影响其支持多主机环境运行的能力。

2)java语言是类型安全和安全的,而像C、C++之类的native语言则是不安全的。因此在使用JNI时,必须格外小心。一个不合适的方法,可以破坏整个程序。出于这个原因,程序在调用JNI功能之前,会先进行安全检查。


作为一般规律,在架构程序时,要尽可能少地定义native方法。这就需要清晰地隔离native代码和程序的其他部分。



什么时候使用JNI


有一些方法可以允许java在不适用JNI时,和native程序进行通信,例如:

1)一个java程序可以和一个native程序,通过TCP/IP连接,或者IPC通信机制通信。

2)一个java程序通过JDBC API和一个传统的数据库连接。

3)一个java程序利用已经发布的技术,例如Java IDL API。


以上共同点是,java程序和native程序不在同一个进程当中。然而有些时候,你需要java程序和native程序运行在同一个进程中,此时JNI就变得很有用处:

1)java API可能不支持程序所需要的依赖于主机环境的某些特定的功能。

2)你可能想要访问已经存在了的native库,并且不想在不同进程间花费复制、传输的开销,那么在同一个进程中加载native库,就非常有效。

3)程序在跨进程时,可能会导致不可接受的内存占用。这种情况在进程需要驻留在同一个客户机上时,变得很常见。在已存在的进程中加载native库比新建一个进程,并且在该进程中加载native库占用的系统资源更少。

4)你可能想要在低级语言中执行一小部分时间关键(time-critical)的代码,例如:集合(assembly)。如果一个3D密集的程序,在图像渲染上面花费了大部分时间,此时你将发现,有必要在集中的代码中编写图像库的核心部分来实现性能最大化。


总之,在驻留在同一个进程中,当java程序必须和native代码进行互操作时,即可使用JNI。



JNI的演变


java平台很早的时候就已经意识到有必要允许java程序和native代码进行互操作了。JDK1.0包含了native方法来允许java程序调用用c、c++编写的函数。许多第三方程序,就像java库(java.lang, java.io, java.net),依赖native方法接口来访问下层主机环境的特性。


不幸的是,JDK1.0中的native方法接口,有两个主要问题:

1)native代码访问作为C结构体的成员的对象。javaVM规范没有定义对象如何在内存中存放。如果给定的java VM存放对象的方式和native方法接口设想的不一致,那么必须要重新编译native方法库。

2)因为JDK1.0的native方法可以获取在java VM中的对象的直接指针,native方法依赖于一个保守的垃圾回收器。任何一个以更高级的垃圾回收算法实现的java VM就不能支持JDK1.0的native方法接口。


JNI就是被设计用来解决这些问题的,它是一个能支持在广泛的主机环境中实现的所有java VM的接口。

1)每个虚拟都能支持更大的native代码。

2)开发工具不必要处理不同类型的native方法接口。

3)最重要的是,程序员可以只写一个版本的native代码,而该代码可以在不同实现方式的java VM上运行。


JNI最早出现在JDK1.1,而此时JDK1.1还是支持旧的native方法接口。旧native方法接口在JDK1.2中被重写为符合JNI标准。



参考资料:

《The Java™ Native Interface Programmer’s Guide and Specification》


后继章节中,不再说明,默认都为参考了该文档







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值