JNI是Java Native Interface的縮寫,中文為JAVA本地調用。使用JNI可以很友善的用我們的Java程式調用C/C++程式。很多時候,某些功能用Java無法實作,比如說涉及到底層驅動的一些功能,這時候我們就可以利用JNI來調用C或者C++程式來實作,這就是JNI的強大之處。但是JNI也有它的缺點,使用java與本地已編譯的代碼互動,通常會喪失平台可移植性。
下面是一個JNI例子,調用C++輸出"hello world":
第一步:建立Java類,在裡面定義一個本地方法(用native關鍵字修飾的方法)
public native void sayHello();
第二步:使用javah指令(javah 類的全路徑)生成本地方法的C++頭檔案
在DOS視窗中進入工程所在目錄,然後執行javah com.test.TestNative指令,執行完之後就會在目前目錄生成一個字尾名為.h的頭檔案,如com_test_TestNative.h,這個頭檔案是根據包名和類名來命名的。
1 /* DO NOT EDIT THIS FILE - it is machine generated */
2 #include <jni.h>
3 /* Header for class com_test_TestNative */
4
5 #ifndef _Included_com_test_TestNative
6 #define _Included_com_test_TestNative
7 #ifdef __cplusplus
8 extern "C" {
9 #endif
10 /*
11 * Class: com_test_TestNative
12 * Method: sayHello
13 * Signature: ()V
14 */
15 JNIEXPORT void JNICALL Java_com_test_TestNative_sayHello
16 (JNIEnv *, jobject);
17
18 #ifdef __cplusplus
19 }
20 #endif
21 #endif
15、16行是對TestNative類中的本地方法sayHello()的聲明。這個h檔案相當于我們在java裡面的接口,這裡聲明了一個 Java_com_test_TestNative_sayHello (JNIEnv *, jobject);方法,然後在我們的本地方法裡面實作這個方法,也就是說我們在編寫C/C++程式的時候所使用的方法名必須和這裡的一緻。
第三步:編寫C/C++本地代碼,生成動态連結庫檔案
首先在VC6.0(當然也可以用其他工具)中建立一個dll工程---Win32 Dynamic-Link Library工程。然後将上面生成的頭檔案com_test_TestNative.h添加到該工程中,然後建立一個源檔案引用該頭檔案并且實作頭檔案中本地函數的功能:
1 #include<iostream.h>
2 #include"com_test_TestNative.h"
3
4 JNIEXPORT void JNICALL Java_com_test_TestNative_sayHello(JNIEnv *env, jobject obj)
5 {
6 cout<<"hello world!"<<endl;
7 }
這裡因為com_test_TestNative.h中引入了jni.h是以要将jni.h加入到VC6.0安裝目錄下的Include目錄中。jni.h在JDK安裝目錄下的include中,同時得件include/win32中的兩個頭檔案jawt_md.h、jni_md.h也導入到VC6.0中。
将所依賴的頭檔案導入之後,我們就可以建構該工程了,按F7就行了,完了會在工程目錄中的Degug目錄下生成一個動态連結庫檔案,我這裡生成的是NativeCode.dll。我們就可以将該dll檔案拷貝到環境變量path所包含的目錄下給咱們的Java程式調用了,為了友善,我們也可以将dll所在的工程目錄加入到環境變量path中去,這樣可以避免每次都要拷貝的麻煩。注意修改環境變量之後要重新開機myeclipse。
第四步:Java調用本地函數
1 package com.test;
2
3 public class TestNative {
4 public native void sayHello();
5
6 /**
7 * @param args
8 */
9 public static void main(String[] args) {
10 System.loadLibrary("NativeCode");
11 TestNative tNative = new TestNative();
12 tNative.sayHello();
13 }
14 }
第10行是加載動态連結庫,JVM隻需要加載一次就可以調用了,“NativeCode”是上面生成的動态連結庫的名字,不含字尾名。
我喜歡,駕馭着代碼在風馳電掣中創造完美!我喜歡,操縱着代碼在随必所欲中體驗生活!我喜歡,書寫着代碼在時代浪潮中完成經典!每一段新的代碼在我手中誕生對我來說就象觀看刹那花開的感動!