good good study, day day up!

Java JNI 简述

2011-12-06

JNI也就是Java Native Interface(Java本地接口)的意思,既然说到”本地”,那么很显然是要与本地代码(C/C++)交互.
Java通过JNI所调用的是本地动态链接库,在Windows上是.dll文件,在Linux上则一般是.so文件.

调用动态链接库中的函数之前,首先要加载库文件,这里不得不提到Windows于Linux上的一点不同:
在Java程序中,我们加载系统库文件是通过以下方式加载的:
System.loadLibrary("xxx");
在Windows系统中,Java会自动寻找名字叫xxx.dll的库文件,而在Linux中,Java会寻找名为libxxx.so的库文件(事实上,linux中后缀名是无关紧要的).
这一点是Linux与Windows很大的不同,Linux中所有的动态链接库文件都是以lib开头的.所以在Linux环境下,Java会自动在xxx之前加一个”lib”,
所以如果我们要加载名为libTEST.so的库文件时,我们只要写
System.loadLibrary("TEST");
即可.了解了这点之后我们就可以开始学习怎样使用JNI.
在Linux环境下:
假设我们要使用Java调用自己编写的一个库文件(假设叫作libTestJNI.so),其中有一个叫做output()的方法,该方法输出
“Hello JNI!”.
那么,我们首先写一个Java类:

public class TestJNI {
    public native void output();
    static {
        try {
            System.loadLibrary("TestJNI");
        }catch(Exception e) {
            System.out.println("Lib not found");
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
    TestJNI test = new TestJNI();
    test.output();
    }
}

注意到我们的output()方法是没有方法体的,而且之前还有一个native关键字修饰,这表明该方法将调用本地方法,该方法将在本地方法中实现.
然后,我们开始生成动态链接库:
先编译刚才写好的Java文件:
        javac TestJNI.java
我们得到一个TestJNI.class文件.
下面要根据该class文件生成.h头文件:
        javah -classpath . TestJNI
生成的头文件为TestJNI.h:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class TestJNI */

#ifndef _Included_TestJNI
#define _Included_TestJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: TestJNI
* Method: output
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_TestJNI_output
    (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

注意TestJNI.h中有一句:

#include 

在之后的编译过程中有可能找不到jni.h这个头文件,这时我们需要把$Java_HOME/include/jni.h以及$Java_HOME/include/linux/jni_md.h这两个头文件放到/usr/include目录下(这样做其实入侵性很强,可以在编译时手动将这两个头文件的位置添加进来,我为了方便起见直接将这两个文件放到了/usr/include下).
可以看到,javah工具自动生成了这个头文件,然后我们只需要按照这个头文件写c或者cpp的代码就ok了
下面是TestJNI.c的代码:

#include "TestJNI.h"
#include 

void JNICALL Java_TestJNI_output
(JNIEnv * env, jobject obj)
{
    printf("Hello JNI!\n");
}

方法声明可以参照.h文件
现在开始编译TestJNI.c:
gcc -fPIC -shared -o libTestJNI.so TestJNI.c
我们将得到的libTestJNI.so文件,将该文件放到/usr/lib下
然后输入java TestJNI即可看到输出结果:Hello JNI!

在Windows下更加方便,在生成TestJNI.h头文件之后,使用VS2010新建一个dll项目,在该项目中导入TestJNI.h,并且把jni.h及jni_md.h导入项目,然后编写好c或者c++代码即可生成dll文件,将dll文件放在$JAVA_HOME/bin目录下即可.


知识共享许可协议本作品采用知识共享署名 2.5 中国大陆许可协议进行许可,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名(chen)并包含原文链接

作者:chending | Categories:Java | Tags:

发表评论

电子邮件地址不会被公开。 必填项已用*标注