`

Java程序员从笨鸟到菜鸟之(九十六)深入java虚拟机(五)——java本地接口JNI详解

阅读更多

对于java程序员来说, java 语言的好处和优点,我想不用我说了,大家自然会说出很多一套套的。但虽然我们作为 java 程序员,但我们不得不承认 java 语言也有一些它本身的缺点。比如在性能、和底层打交道方面都有它的缺点。所以 java 就提供了一些本地接口,他主要的作用就是提供一个标准的方式让 java 程序通过虚拟机与原生代码进行交互,这也就是我们平常常说的 java 本地接口( JNI —— javanativeInterface 。它使得在Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语言(如 C C++ 和汇编语言)编写的应用程序和库进行互操作。 JNI最重要的好处是它没有对底层 Java 虚拟机的实现施加任何限制。因此, Java 虚拟机厂商可以在不影响虚拟机其它部分的情况下添加对 JNI 的支持。程序员只需编写一种版本的本地应用程序或库,就能够与所有支持 JNI Java 虚拟机协同工作。 我们来看一下为什么要与原生代码进行交互:


 

一:提高应用程序性能 。我们知道java对于 c/c++ 、汇编语言来说,显得比较“高级”。其实这里的高级就是简化了程序员的工作。很多底层的东西都让 java 虚拟机做了。但毕竟相对于直接访问底层来讲, java 多了一步虚拟机的过程,所以在性能上比着这些原生语言稍微有点慢。


二:实现一些与底层相关的功能 Java 平台提供的标准类库,还有强大的 API ,虽然能完成大部分功能。但有些和底层硬件打交道的功能在 javaAPI 提供的类库中还是无法完成。


三:与已有的使用原生代码编写的程序进行集成 在于操作系统上由c 或者 c++ 等原生语言编写的软件进行集 0 成的时候,可以用 JNI


 

JNI接口函数和指针

平台相关代码是通过调用JNI 函数来访问 Java 虚拟机功能的。 JNI 函数可通过 接口指针来获得。接口指针是指针的指针,它指向一个指针数组,而指针数组中的每个元素又指向一个接口函数。每个接口函数都处在数组的某个预定偏移量中。下图 说明了接口指针的组织结构。




JNI接口的组织类似于 C++ 虚拟函数表或 COM 接口。使用接口表而不使用硬性编入的函数表的好处是使 JNI 名字空间与平台相关代码分开。虚拟机可以很容易地提供多个版本的 JNI 函数表。例如,虚拟机可支持以下两个 JNI 函数表:

·一个表对非法参数进行全面检查,适用于调试程序;

·另一个表只进行 JNI 规范所要求的最小程度的检查,因此效率较高。

JNI接口指针只在当前线程中有效。因此,本地方法不能将接口指针从一个线程传递到另一个线程中。实现 JNI 的虚拟机可将本地线程的数据分配和储存在 JNI 接口指针所指向的区域中。


本地方法将JNI 接口指 针当作参数来接受。虚拟机在从相同的Java 线程中对本地方法进行多次调用时,保证传递给该本地方法的接口指针是相同的。但是,一个本地方法可被不同的 Java 线程所调用,因此可以接受不同的 JNI 接口指针。


 

 

 

(1)编写 Java 类代码


其中,需要JNI 实现的方法应当用 native 关键字声明。在该类中,用 System 1oadLibrary() 方法加载需要的动态链接库。关键代码如下:
//Compute.java
publicclassCompute{
publicnativedoublesqrt(doubleparams);
static{
//调用动态链接库
System loadLibrary( compute”)
}

(2)编译成字节代码


在这个过程中,由于采用了native 关键字声明, Java 编译器会忽视没有代码体的 JNI 方法部分。

(3)生成相关 JNI 方法的头文件


这个过程的实现一般是通过利用jlavah-jni *class生成的 (-jni可以省略) ,也可以手工生成该文件;但是由于Java 虚拟机是根据一定的命名规范完成对 JNI 方法的调用,所以手工编写头文件需要特别小心。
上述文件产生的头文件部分代码如下:
//Compute.h
extern C {
JNIEXPORTjdoubleJNICALLJava_Compute_comp(JNI-Env*,jobject,jdoubleArray)


JNI函数名称分为三部分:首先是 Java 关键字,供 Java 虚拟机识别;然后是调用者类名称 ( 全限定的类名,其中用下划线代替名称分隔符 ) ;最后是对应的方法名称,各段名称之间用下划线分割。


JNI函数的参数也由三部分组成:首先是 JNIEnv*, 是一个指向 JNI 运行环境的指针;第二个参数随本地方法是静态还是非静态而有所不同一一非静态本地方法的第二个参数是对对象的引用,而静态本地方法的第二个参数是对其 Java 类的引用;其余的参数对应通常 Java 方法的参数,参数类型需要根据一定规则进行映射。


(4)编写相应方法的实现代码


在编码过程中,需要注意变量的长度问题,例如Java 的整型变量长度为 32 位,而 C 语言为 16 位,所以要仔细核对变量类型映射表,防止在传值过程中出现问题。


(5) JNI 实现代码编译成动态链接库


编译过程是利用C C++ 编译器实现的,windows 平台上,编译和连接的结果是动态链接库 DLL 文件。 当要使用生成的动态链接库时,调用者类中需要显式调用该链接库dll文件
经过上述处理,基本上完成了一个包含本地化方法的Java 类的开发。


附录:将Jav 类型映射到本地 C 类型


基本类型和本地等效类型

Java类型

本地类型

说明

boolean

jboolean

无符号,8

byte

jbyte

无符号,8

char

jchar

无符号,16

short

jshort

有符号,16

int

jint

有符号,32

long

jlong

有符号,64

float

jfloat

32

double

jdouble

64

void

void

N/A

为了使用方便,特提供以下定义。

#defineJNI_FALSE0

#defineJNI_TRUE1

jsize整数类型用于描述主要指数和大小:

typedefjintjsize;


 

故障排除


当使用JNI Java 程序访问本机代码时,您会遇到许多问题。您会遇到的三个最常见的错误是:

1)无法找到动态链接。它所产生的错误消息是:java.lang.UnsatisfiedLinkError 。这通常指无法找到共享库,或者无法找到共享库内特定的本机方法。

2)无法找到共享库文件。当用 System.loadLibrary(Stringlibname) 方法(参数是文件名)装入库文件时,请确保文件名拼写正确以及没有指定扩展名。还有,确保库文件的位置在类路径中,从而确保 JVM 可以访问该库文件。

3)无法找到具有指定说明的方法。确保您的 C/C++ 函数实现拥有与头文件中的函数说明相同的说明。


 

结束语

Java 调用 C C++ 本机代码(虽然不简单)是 Java 平台中一种良好集成的功能。虽然 JNI 支持 C C++ ,但 C++ 接口更清晰一些并且通常比 C 接口更可取。正如您已经看到的,调用 C C++ 本机代码需要赋予函数特殊的名称,并创建共享库文件。当利用现有代码库时,更改代码通常是不可取的。要避免这一点,在 C++ 中,通常创建代理代码或代理类,它们有专门的 JNI 所需的命名函数。然后,这些函数可以调用底层库函数,这些库函数的说明和实现保持不变。



参考资料:《java本地接口规范》


------------------------------------------------------------------------------------------------------------

《Java程序员由笨鸟到菜鸟》电子版书正式发布,欢迎大家下载

 

http://blog.csdn.net/csh624366188/article/details/7999247



 

分享到:
评论

相关推荐

    java程序员-从笨鸟到菜鸟.pdf

    java程序员-从笨鸟到菜鸟.pdf

    [网盘]java程序员由菜鸟到笨鸟.pdf

    ### Java程序员成长之路——从菜鸟到笨鸟 #### 一、引言 《Java程序员由菜鸟到笨鸟》是一本由曹胜欢编写的书籍,旨在帮助初学者掌握Java编程的基础知识,并逐步进阶至更高级的应用场景。本书不仅适合初学者作为...

    JAVA程序员 从笨鸟到菜鸟.pdf

    曹胜欢在《JAVA程序员 从笨鸟到菜鸟.pdf》中分享了他个人学习Java的经历,从迷茫到逐渐成长的过程。他强调了自学的重要性,并鼓励初学者不要怕走弯路,同时希望自己的经验可以帮助到同样在学习Java的初学者。 2. ...

    java程序员从笨鸟到菜鸟

    ### Java程序员从笨鸟到菜鸟 #### 一、开发环境搭建与基本语法 ##### 开发环境搭建 在开始Java的学习之前,首先需要搭建一个合适的开发环境。这通常涉及到以下步骤: 1. **JDK(Java Development Kit)安装**:...

    Java程序员由菜鸟到笨鸟学习文档

    Java程序员的成长之路是一个充满挑战与探索的过程,从初学者到熟练掌握各项技能,需要系统性的学习和实践。"Java程序员由菜鸟到笨鸟学习文档"就是这样一个旨在帮助初入Java世界的学习者逐步进阶的资源。它覆盖了从...

    《Java程序员-从笨鸟到菜鸟》PDF下载

    资源名称:《Java程序员-从笨鸟到菜鸟》PDF 下载资源目录:作者简介:..........................................................................................................................................

    java程序员由菜鸟到笨鸟

    《java程序员由菜鸟到笨鸟》 刚开始学习java时看过的一个学习资料。 其中包括开发环境搭建、面向对象、Javascript、设计模式、SSH、jquery、java虚拟机等内容。 设计内容较广,可以学习参考。

    [网盘]java程序员由菜鸟到笨鸟.pdf.2018_03_19

    以上内容只是《Java程序员由菜鸟到笨鸟》这本书中可能涵盖的部分知识点。对于初学者来说,系统地学习这些基础知识是非常重要的,因为它们构成了Java编程的基础,也是进一步学习高级主题的基石。希望这些内容能够帮助...

    [网盘]java程序员由菜鸟到笨鸟.pdf.2018_03_17

    根据提供的文件信息,“Java程序员由菜鸟到笨鸟”是一本旨在帮助初学者成长为合格Java开发者的书籍。本书作者为曹胜欢,发布日期为2018年3月17日。以下是从该书的标题、描述以及部分可能包含的内容中提炼出的关键...

    黑马程序员-Java语言进阶-源码、教程笔记.zip

    day01_Object类、常用API day02_Collection、泛型 day03_List、Set、数据结构、Collections day04_Map,斗地主案例 day05_异常,线程 day06_线程、同步 day07_等待与唤醒案例、线程池、Lambda...Java基础小节练习题答案

    java游戏笨鸟

    《Java游戏:笨鸟》(也称为FlappyBird)是一款基于Java编程语言开发的简单游戏,旨在帮助初学者更好地理解和掌握Java编程基础。这款游戏的实现涉及了许多Java编程的关键概念和技术,下面将对这些知识点进行详细阐述...

Global site tag (gtag.js) - Google Analytics