Java 调用本地Native接口指引

来源:互联网 发布:麻纱布料淘宝 编辑:程序博客网 时间:2024/05/24 00:49

Java本地接口允许java用户用代码与其他语言接口交互的一种方法,native方法允许java语言调用其他语
言,增加了代码的灵活性

1、Java本地接口的好处

通过使用Java接口,可以增加代码的灵活性与重用性,假如我们想在java里用一段C语言的代码实现的功能,我们不用全部重写所有C语言代码,而是可以加一个C语言接口类,与java交互即可。
通过java接口,还可以提升java程序的性能瓶颈,我们知道,java在运行的时候由于需要运行在jvm上,因此效率会有所下降,这也是为了跨平台性做了一个折中的办法,通过jni,我们可以将一些代码放在native代码中,通常native代码的速度比java代码快很多,因此可以提升java程序的性能。

2、Java本地方法的开发过程
目的:实现一个Hello类,在Hello类里面定义一个native’的方法,并且这个方法转由C语言实现。

首先,我们创建一个Hello类:

public class Hello {      public native void sayHi(); //1      static { System.loadLibrary("hello"); } //2      public static void main (String[] args) {          Hello hello = new Hello();          System.out.println("I will Print:");          hello.sayHi();//3      }  } 

其中,第一步创建一个native的sayHi方法,方法的实现并未实现,而是由下面的C语言来实现。
第二步加载C语言库,在windows下,库名为hello.dll,在Linux下,库名为libhello.so,在macos系统下库名为libhello.jnilib
第三步在main方法里面调用我们定义的native方法,来验证我们的方法是否成功执行。

其次,通过javac工具编译这个类:

$ javac Hello.java   

如果是有包的话需要加上包路径名。

然后,用javah工具创建native的.h头文件,这个文件为自动生成

[plain] view plain copy$ javah -jni Hello  

创建好之后,我们的文件夹中就多了个Hello.h头文件:

/* DO NOT EDIT THIS FILE - it is machine generated */  #include <jni.h>  /* Header for class Hello */  #ifndef _Included_Hello  #define _Included_Hello  #ifdef __cplusplus  extern "C" {  #endif  /*  * Class:     Hello  * Method:    sayHi  * Signature: ()V  */  JNIEXPORT void JNICALL Java_Hello_sayHi    (JNIEnv *, jobject);  #ifdef __cplusplus  }  #endif  #endif 

这个文件里定义了我们需要实现的函数原型:

JNIEXPORT void JNICALL Java_Hello_sayHi    (JNIEnv *, jobject);  

然后我们需要实现具体的定义,创建一个hello.c文件:

#include<stdio.h>  #include"Hello.h"    JNIEXPORT void JNICALL  Java_Hello_sayHi(JNIEnv *env, jobject obj) {      printf("Hello World\n");  }  

在实现中,我们需要include我们刚才自动创建好的.h文件,并且实现它定义的函数。

然后我们生成.so库文件:

$ gcc -o libhello.so -fPIC -lc -shared -I /usr/lib/jvm/java/include -I /usr/lib/jvm/java/include/linux hello.c  

-o为输出文件名,不能随意更改,要以lib+库名(就是java代码里loadLibrary里的字符串)+.so命名
-I 由于需要jni.h和其他的一些头文件,需要加上依赖的头文件路径

然后我们需要把当前文件目录加入库文件路径中:

[plain] view plain copy$ export LD_LIBRARY_PATH=.  

ok,至此已经全部完成操作,最后我们java Hello就可以执行代码了。

3、可能出错的地方
常见的错误有两个地方,一个是: java.lang.UnsatisfiedLinkError: no HelloWorld in java.library.path,这个是由于找不到库文件所致的,原因有很多,最常见的是文件名规则设置错误,或者没有export LD_LIBRARY_PATH使得java找不到库文件。
还有一个错误的是:Exception in thread “main” java.lang.UnsatisfiedLinkError: xxx.xxx.HelloWorld.myprint()V,这个是由于我们的库虽然找到了,但是定义却是错误的,大多数原因是我们自己写的函数名有错误,或者参数有错误所致,仔细检查一遍即可。

转载至:http://blog.csdn.net/runningtortoises/article/details/51548351

原创粉丝点击