如何在linux下創建一個簡單的JNI程序HelloWorld
Posted on 2010-12-07 08:39 楊書童 閱讀(1574) 評論(2) 編輯 收藏 引用 所屬分類: 基礎知識-基礎語言JNI全名是Java Native Interface,通過JNI技術可以實現Java和其他編程語言的互相調用。這里我們使用的是Java和C的互相調用,Java提供本地接口,C實現該本地接口。
我使用的是RHEL 5,主要是為了測試一下在Linux平臺下,了解JNI技術是如何實現的。通過一個HelloWorld實例,具體過程在下面講解。
首先,實現的是Java本地接口Hello.java,代碼如下所示:

class HelloWorld
{

public native void sayHello();


static
{
System.loadLibrary("HelloWorld");
}


public static void main(String[] args)
{
(new HelloWorld()).sayHello();
}
}
其中,方法聲明為native,其實HelloWorld類就相當于一個接口,是為其他編程語言聲明的接口。System.loadLibrary("HelloWorld");語句是一個static塊,也就是在該HelloWorld類加載的時候進行執行。其中,該語句實現了加載本地的動態連接庫(DLL),在Linux平臺下,動態連接庫文件是以.so作為擴展名的,也就是標準對象(Standard Object)。
對該本地接口類進行編譯:
[root@localhost jni]# javac HelloWorld.java
接著,通過編譯的HelloWorld.class文件,生成C語言的頭文件,執行命令:
[root@localhost jni]# javah -jni HelloWorld
可以看到,在當前目錄下生成一個HelloWorld.h文件,該文件就是C的接口文件,為使用C實現Java接口中定義的方法,可以發現在HelloWorld.h中有一個方法聲明:


/**//* DO NOT EDIT THIS FILE - it is machine generated */

#ifndef __HelloWorld__
#define __HelloWorld__

#include <jni.h>

#ifdef __cplusplus
extern "C"


{
#endif

JNIEXPORT void JNICALL Java_HelloWorld_sayHello (JNIEnv *env, jobject);

#ifdef __cplusplus
}
#endif

#endif /* __HelloWorld__ */
然后,用C實現該方法,在HelloWorld.c文件中,代碼如下:
#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>


JNIEXPORT void JNICALL Java_HelloWorld_sayHello (JNIEnv *env, jobject obj)
{
printf("Hello,the World!!!");
}
這里,方法簽名為Java_HelloWorld_sayHello (JNIEnv *env, jobject obj),添加了形參obj,否則無法通過編譯。
接下來,生成動態連接庫libHelloWorld.so,執行命令:
[root@localhost jni]# gcc -fPIC -shared -o libHelloWorld.so HelloWorld.c
可以在當前目錄下看到libHelloWorld.so,動態連接庫文件名稱以lib開頭。將該文件拷貝到usr/lib目錄下面,就可以測試了。
現在執行如下命令進行測試:
[root@localhost jni]# java HelloWorld
輸出如下:
Hello,the World!!!
這只是一個非常簡單的例子,主要是了解JNI在Linux下該如何用。在實際應用中,可能會非常復雜,并且要記住,一旦使用了JNI技術,系統的可移植性被破壞了。有些應用中,正是基于這種特性實現,比如限制軟件的傳播使用,保護開發商權益,等等。
我使用的是RHEL 5,主要是為了測試一下在Linux平臺下,了解JNI技術是如何實現的。通過一個HelloWorld實例,具體過程在下面講解。
首先,實現的是Java本地接口Hello.java,代碼如下所示:



















其中,方法聲明為native,其實HelloWorld類就相當于一個接口,是為其他編程語言聲明的接口。System.loadLibrary("HelloWorld");語句是一個static塊,也就是在該HelloWorld類加載的時候進行執行。其中,該語句實現了加載本地的動態連接庫(DLL),在Linux平臺下,動態連接庫文件是以.so作為擴展名的,也就是標準對象(Standard Object)。
對該本地接口類進行編譯:
[root@localhost jni]# javac HelloWorld.java
接著,通過編譯的HelloWorld.class文件,生成C語言的頭文件,執行命令:
[root@localhost jni]# javah -jni HelloWorld
可以看到,在當前目錄下生成一個HelloWorld.h文件,該文件就是C的接口文件,為使用C實現Java接口中定義的方法,可以發現在HelloWorld.h中有一個方法聲明:
























然后,用C實現該方法,在HelloWorld.c文件中,代碼如下:










這里,方法簽名為Java_HelloWorld_sayHello (JNIEnv *env, jobject obj),添加了形參obj,否則無法通過編譯。
接下來,生成動態連接庫libHelloWorld.so,執行命令:
[root@localhost jni]# gcc -fPIC -shared -o libHelloWorld.so HelloWorld.c
可以在當前目錄下看到libHelloWorld.so,動態連接庫文件名稱以lib開頭。將該文件拷貝到usr/lib目錄下面,就可以測試了。
現在執行如下命令進行測試:
[root@localhost jni]# java HelloWorld
輸出如下:
Hello,the World!!!
這只是一個非常簡單的例子,主要是了解JNI在Linux下該如何用。在實際應用中,可能會非常復雜,并且要記住,一旦使用了JNI技術,系統的可移植性被破壞了。有些應用中,正是基于這種特性實現,比如限制軟件的傳播使用,保護開發商權益,等等。