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

Java 呼叫 VC++ 元件:JNI 實作完整指南

     編輯:Java 相關知識

前言:為什麼需要 JNI?

Java 最大的優勢在於「一次編寫,到處執行」的跨平台特性,但這也成為雙面刃——當 Java 程式需要存取平台特定功能(如 Windows API、硬體驅動程式、既有的 C/C++ 函式庫)時,純 Java 無法直接完成。Java Native Interface (JNI) 正是解決這個問題的橋樑,它允許 Java 程式碼呼叫原生程式碼(C/C++),並反之亦然。

核心概念

  • Native 方法:在 Java 中以 native 關鍵字宣告,實作邏輯寫在 C/C++ 中。
  • 靜態區塊:用 static { System.loadLibrary("..."); } 在類別載入時將原生函式庫(.dll / .so)載入記憶體。

實作步驟

1. 撰寫 Java 類別並宣告 native 方法

public class JNITest {
    static {
        System.loadLibrary("JNITest"); // 載入 JNITest.dll (Windows) 或 libJNITest.so (Linux)
    }

    native void showMessage(String str); // 宣告 native 方法

    public JNITest() {
        System.out.println("In the constructor of the Java program");
    }

    public static void main(String[] args) {
        JNITest test = new JNITest();
        test.showMessage("Passing string from Java");
    }
}

2. 編譯並產生 C/C++ 標頭檔

  1. javac JNITest.java 產生 JNITest.class
  2. 執行 javah -jni JNITest 產生 JNITest.h

產生的標頭檔會包含如下函式簽名:

JNIEXPORT void JNICALL Java_JNITest_showMessage(JNIEnv *, jobject, jstring);

3. 建立 VC++ DLL 專案並實作原生方法

  • 在 Visual Studio 建立 Win32 DLL 專案。
  • 將 JDK 的 include 與 include/win32 目錄加入專案的 Include 路徑。
  • 引入 jni.h 與剛產生的 JNITest.h。

4. 字串轉換與資源釋放

Java 字串(jstring)在 C++ 中需透過 JNIEnv 轉換為 C 風格字串,用畢必須釋放,否則會導致 JVM 記憶體洩漏甚至崩潰。

JNIEXPORT void JNICALL Java_JNITest_showMessage(
    JNIEnv *env, jobject obj, jstring str) {

    const char *cStr = env->GetStringUTFChars(str, 0); // 轉換
    if (cStr == NULL) return; // 記憶體不足

    MessageBox(0, cStr, "Message from VC++", 0); // 呼叫 Windows API

    env->ReleaseStringUTFChars(str, cStr); // 釋放
}

5. 編譯 DLL 並執行

  • 編譯產生 JNITest.dll。
  • 將 DLL 放在 Java 類別檔同目錄或 java.library.path 指定路徑。
  • 執行 java JNITest 即可看到 VC++ 彈出的訊息框。

常見錯誤與除錯

  • UnsatisfiedLinkError:檢查 DLL 檔名、路徑、方法簽名是否與 .h 檔一致。
  • 忘記 ReleaseStringUTFChars 導致 JVM Crash。
  • 32/64 位元不匹配:JVM 與 DLL 必須相同位元數。

總結

JNI 雖強大,但增加了部署複雜度與平台相依性。建議僅在必要時(如呼叫 OS API、效能關鍵路徑、整合既有 C/C++ 資產)使用,並妥善封裝介面,維持 Java 端程式碼純粹性。

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