关闭

Java 调用本地Native接口指引

825人阅读 评论(0) 收藏 举报

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头文件,这个文件为自动生成
$ 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和其他的一些头文件,需要加上依赖的头文件路径

然后我们需要把当前文件目录加入库文件路径中:
$ 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,这个是由于我们的库虽然找到了,但是定义却是错误的,大多数原因是我们自己写的函数名有错误,或者参数有错误所致,仔细检查一遍即可。
1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:194995次
    • 积分:5388
    • 等级:
    • 排名:第5237名
    • 原创:329篇
    • 转载:36篇
    • 译文:1篇
    • 评论:6条
    最新评论