初识JNI

来源:互联网 发布:俄罗斯与乌克兰知乎 编辑:程序博客网 时间:2024/05/17 11:33

JNIJava Native Interface的缩写,它的设计目的是:
The standard Java class library may not support theplatform-dependent features needed by your application.You may already have alibrary or application written in another programming language and you wish tomake it accessible to Java applications. You may want to implement a smallportion of time-critical code in a lower-level programming language, such asassembly, and then have your Java application call these functions.

2JNI的书写步骤
  编写带有native声明的方法的java
  使用javac命令编译所编写的java
  使用javah ?jnijava类名生成扩展名为h的头文件
  使用C/C++实现本地方法
  将C/C++编写的文件生成动态连接库

1) 编写java程序:
  这里以
HelloWorld为例。
  代码1:
  class HelloWorld {
  publicnative void displayHelloWorld();
  
static {
  System.loadLibrary("hello");
  }
  public static voidmain(String[] args) {
  newHelloWorld().displayHelloWorld();
  }
  }

声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明改方法为native的,并且不能实现。其中方法的参数和返回值在后面讲述。

Load动态库:System.loadLibrary("hello");加载动态库(我们可以这样理解:我们的方法displayHelloWorld()没有实现,但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载的。同时需要注意的是System.loadLibrary();的参数“hello”是动态库的名字。

2) 编译没有什么好说的了
  
javac HelloWorld.java
  
3) 生成扩展名为h的头文件
  javah ?jni HelloWorld

头文件的内容:
  
/* DO NOT EDIT THIS FILE- it is machine generated */
  #include <jni.h>
  /* Header for classHelloWorld */
  #ifndef_Included_HelloWorld
  #define_Included_HelloWorld
  #ifdef __cplusplus
  extern "C" {
  #endif
  /*
  * Class:   HelloWorld
  * Method:  displayHelloWorld
  * Signature: ()V
  */
  JNIEXPORT void JNICALLJava_HelloWorld_displayHelloWorld
  (JNIEnv *, jobject);
  #ifdef __cplusplus
  }
  #endif
  #endif

(这里我们可以这样理解:这个h文件相当于我们在java里面的接口,这里声明了一个Java_HelloWorld_displayHelloWorld(JNIEnv *, jobject);方法,然后在我们的本地方法里面实现这个方法,也就是说我们在编写C/C++程序的时候所使用的方法名必须和这里的一致)。

4)编写本地方法
  实现由
javah命令生成的头文件里面声明的方法名相同的方法。

代码2:
  

  1 #include <jni.h>
  2 #include"HelloWorld.h"
  3 #include<stdio.h>
  4 JNIEXPORTvoid JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
  
printf("Hello world!\n");
  return;
  }

注意代码2中的第1行,需要将jni.h(该文件可以在%JAVA_HOME%/include文件夹下面找到)文件引入,因为在程序中的JNIEnv、jobject等类型都是在该头文件中定义的;另外在第2行需要将HelloWorld.h头文件引入(我是这么理解的:相当于我们在编写java程序的时候,实现一个接口的话需要声明才可以,这里就是将HelloWorld.h头文件里面声明的方法加以实现。当然不一定是这样)。然后保存为HelloWorldImpl.c就ok了。

5) 生成动态库 
  这里以在
Windows中为例,需要生成dll文件。在保存HelloWorldImpl.c文件夹下面,使用VC的编译器cl成。
  
cl -I%java_home%\include-I%java_home%\include\win32 -LD HelloWorldImp.c -Fehello.dll

注意:生成的dll文件名在选项-Fe后面配置,这里是hello,因为在HelloWorld.java文件中我们loadLibary的时候使用的名字是hello。当然这里修改之后那里也需要修改。另外需要将-I%java_home%\include-I%java_home%\include\win32参数加上,因为在第四步里面编写本地方法的时候引入了jni.h文件。  6) 运行程序   javaHelloWorld就ok。^_^
  
Java 环境和语言对于应用程序开发来说是非常安全和高效的。但是,一些应用程序却需要执行纯 Java程序无法完成的一些任务,比如:与旧有代码集成,避免重新编写。实现可用类库中所缺少的功能。举例来说,在 Java语言中实现 ping 时,您可能需要 Internet Control Message Protocol (ICMP)功能,但基本类库并未提供它。最好与使用 C/C++编写的代码集成,以充分发掘性能或其他与环境相关的系统特性。解决需要非 Java代码的特殊情况。举例来说,核心类库的实现可能需要跨包调用或者需要绕过其他 Java安全性检查。JNI 允许您完成这些任务。它明确分开了 Java 代码与本机代码(C/C++)的执行,定义了一个清晰的 API在这两者之间进行通信。从很大程度上说,它避免了本机代码对 JVM的直接内存引用,从而确保本机代码只需编写一次,并且可以跨不同的 JVM实现或版本运行。


原创粉丝点击