原則上來說,“100%純Java”的解決方法是最好的,但有些情況下必須使用本地方法。特別是在以下三種情況:
- 需要訪問Java平台無法訪問的系統特性和設備;
- 通過基准測試,發現Java代碼比其他語言編寫的等價代碼慢得多;
- 其他語言編寫的代碼已經經過大量測試和調試,並且知道如何將其導出到所有的目標平台上。
Java平台有一個用於和本地C、C++代碼進行互操作的API,稱為Java本地接口(JNI)。下面將舉例討論Linux平台下的JNI編程。
1. 創建java類文件
創建一個nativeTest包,在包下新建HelloNative.java文件。
1 package nativeTest; 2 3 /** 4 * Created by jiax on 2016/12/30. 5 */ 6 public class HelloNative { 7 // 靜態初始化代碼塊,保證虛擬機在第一次使用該類時就會裝載庫 8 static { 9 System.loadLibrary( "HelloNative" ); 10 } 11 12 // native 關鍵字表示本地方法,提醒編譯器該方法將在外部定義 13 public static native void greeting(); 14 15 // 測試greeting()函數 16 public static void main(String[] args) { 17 greeting(); 18 } 19 }
2. 生成.h頭文件
使用以下命令生成一個C的頭文件,nativeTest_HelloNative.h
1 javac HelloNative.java 2 cd .. 3 javah nativeTest.HelloNative
生成的nativeTest_HelloNative.h如下:

1 /* DO NOT EDIT THIS FILE - it is machine generated */ 2 #include <jni.h> 3 /* Header for class nativeTest_HelloNative */ 4 5 #ifndef _Included_nativeTest_HelloNative 6 #define _Included_nativeTest_HelloNative 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 /* 11 * Class: nativeTest_HelloNative 12 * Method: greeting 13 * Signature: ()V 14 */ 15 JNIEXPORT void JNICALL Java_nativeTest_HelloNative_greeting 16 (JNIEnv *, jclass); 17 18 #ifdef __cplusplus 19 } 20 #endif 21 #endif
這個文件是在nativeTest文件夾外生成的,需要拖到nativeTest文件夾里面。
3. 創建.c文件
新建一個HelloNative.c文件,寫出greeting()函數的實現代碼。
1 #include <stdio.h> 2 #include "nativeTest_HelloNative.h" 3 4 JNIEXPORT void JNICALL Java_nativeTest_HelloNative_greeting(JNIEnv *env, jobject c1) { 5 printf("Hello Native!!\n"); 6 }
4. 編譯一個動態鏈接庫
使用Linux下的gcc編譯器,命令如下:
gcc -fPIC -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -shared -o libHelloNative.so HelloNative.c
生成libMyNative.so文件,此時整個nativeTest目錄文件結構如下:
5. 運行測試
輸入如下命令運行HelloNative.class文件。
java nativeTest.HelloNative
如果出現如下錯誤:
則需要把libHelloNative.so所在文件夾加入java.library.path,使用命令:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:..../nativeTest
最終結果如下。
6 總結
總的來說,將一個本地方法鏈接到Java程序中需要經過以下5個步驟:
- 在Java類中聲明一個本地方法;
- 運行javah以獲得包含該方法的C聲明的頭文件;
- 用C實現該本地方法;
- 將代碼置於共享類庫中;
- 在Java程序中加載該類庫。
附錄——本文中用到的工具版本
JDK——1.8.0_111
gcc——4.8.5