首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JNI 實戰:Java 呼叫 C/C++ 產生的 DLL

     編輯:Java 相關知識

流程總覽

  1. 編寫 Java 類別,宣告 native 方法。
  2. javac 編譯 → javah 產生 C/C++ 標頭檔 (.h)。
  3. 在 Visual Studio 建立 DLL 專案,實作 JNI 函數。
  4. 編譯產生 .dll,置於 Java 類別路徑或 java.library.path。
  5. Java 中 System.loadLibrary 載入並呼叫。

步驟 1:Java 類別與 native 宣告

public class Main {
    // native 方法:傳入 byte[] 與長度,回傳字串長度
    public native static int getStrNum(byte[] str, int strLen);

    static {
        // 載入 DLL(檔名不含副檔名)
        System.loadLibrary("MakeDLL");
    }

    public static void main(String[] args) {
        Main inst = new Main();
        String test = "haha";
        int len = inst.getStrNum(test.getBytes(), test.length());
        System.out.println("Length: " + len); // 輸出 4
    }
}

步驟 2:產生標頭檔

javac Main.java
javah Main

產生 Main.h,包含 JNI 函數原型:

JNIEXPORT jint JNICALL Java_Main_getStrNum
  (JNIEnv *, jclass, jbyteArray, jint);

步驟 3:Visual Studio 建立 DLL 專案

  1. 新專案 → Win32 Console Application → 名稱 MakeDLL → Empty Project。
  2. 專案屬性 → General → Configuration Type: Dynamic Library (.dll)。
  3. C/C++ → General → Additional Include Directories 加入:
    $(JAVA_HOME)\include
    $(JAVA_HOME)\include\win32
  4. 將 Main.h 加入專案。
  5. 新增 main.cpp 實作:
#include "Main.h"
#include 

JNIEXPORT jint JNICALL Java_Main_getStrNum
  (JNIEnv *env, jclass cls, jbyteArray str, jint strLen) {
    // 取得 byte[] 內容指標
    jbyte *buf = (*env)->GetByteArrayElements(env, str, 0);
    // 手動加結束符(Java 字串不保證以 \0 結尾)
    buf[strLen] = '\0';
    // 計算長度
    jint len = strlen((char*)buf);
    // 釋放陣列元素
    (*env)->ReleaseByteArrayElements(env, str, buf, 0);
    return len;
}
  1. F7 編譯連結 → 產生 MakeDLL.dll。

步驟 4:Java 執行

  • 將 MakeDLL.dll 複製到 Main.class 同目錄,或設定 -Djava.library.path=.。
  • 執行 java Main → 輸出 Length: 4。

JNI 關鍵 API 速查

操作JNI 函數說明
取得 primitive 陣列元素GetByteArrayElements, GetIntArrayElements, ...回傳 C 指標,用畢須 Release
釋放陣列元素ReleaseByteArrayElements, ...mode: 0=複製回寫, JNI_COMMIT=只寫回, JNI_ABORT=放棄修改
建立新陣列NewByteArray, NewIntArray, ...回傳 jarray
設定陣列區域SetByteArrayRegion, ...從 C 緩衝區複製資料到 Java 陣列
字串轉換NewStringUTF, GetStringUTFCharsUTF-8 編碼互轉

常見問題

  • UnsatisfiedLinkError:DLL 找不到、架構不符 (32/64-bit)、函數簽名不符(檢查 javah 產生的標頭)。
  • 記憶體洩漏:忘記 Release...ArrayElements。
  • 例外處理:JNI 代碼中若拋出例外,需用 (*env)->ThrowNew 或讓 Java 端捕捉。

結語

JNI 讓 Java 能重用 C/C++ 高效能庫或系統級 API,但增加了部署複雜度與風險。現代替代方案包括 JNA (Java Native Access)、JNR-FFI、或透過 gRPC/REST 進行進程間通訊,視情況選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved