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

Java JNI 快速入門教程:從 Java 調用 C/C++ 完整實戰流程

     編輯:Java 相關知識

Java JNI (Java Native Interface) 完整實戰指南

JNI 讓 Java 程式能調用 C/C++ 編寫的本地庫,解決效能敏感、硬體控制、legacy 代碼複用等場景。本文以「字串拼接」為例,完整演示從 Java 類定義到 C 實現、編譯生成動態庫、運行驗證的全流程。

完整實戰步驟

1. 定義包含 native 方法的 Java 類

public class Test {
    // 宣告 native 方法
    public native String helloworld(String text);
    
    public static void main(String[] args) {
        // 載入動態庫:Windows 對應 Test2.dll,Linux 對應 Test2.so
        System.loadLibrary("Test2");
        Test ts = new Test();
        String result = ts.helloworld("world");
        System.out.println(result); // 預期輸出:helloworld
    }
}

2. 編譯 Java 類生成 .class 文件

javac Test.java

3. 生成 C/C++ 頭文件

javah Test

生成 Test.h,關鍵函數簽名:

JNIEXPORT jstring JNICALL Java_Test_helloworld (JNIEnv *, jobject, jstring);
  • JNIEXPORT:導出符號
  • jstring:返回 Java String 對應類型
  • JNICALL:呼叫慣例
  • Java_Test_helloworld:固定命名規則 Java_全類名_方法名
  • 參數:JNIEnv* (JNI 環境指標)、jobject (this 參照)、jstring (Java 字串參數)

4. 實現 C 代碼

#include "Test.h"
#include <string.h>

JNIEXPORT jstring JNICALL Java_Test_helloworld (JNIEnv *env, jobject obj, jstring string) {
    // 1. Java 字串 (UTF-16) 轉 C 字串 (UTF-8)
    const char* str = (*env)->GetStringUTFChars(env, string, 0);
    
    // 2. C 字串操作:前綴 "hello"
    char cap[128] = "hello";
    strcat(cap, str);
    
    // 3. 釋放 JNI 佔用的記憶體 (關鍵!防止記憶體洩漏)
    (*env)->ReleaseStringUTFChars(env, string, str);
    
    // 4. C 字串轉 Java 字串返回
    return (*env)->NewStringUTF(env, cap);
}

5. 編譯生成動態庫

Windows (MinGW/GCC):

gcc -I "D:\Program Files\Java\jdk1.8.0_45\include" \
    -I "D:\Program Files\Java\jdk1.8.0_45\include\win32" \
    --shared Test2.c -o Test2.dll

Linux:

gcc -fPIC -shared -I ${JAVA_HOME}/include -I ${JAVA_HOME}/include/linux Test2.c -o libTest2.so

6. 運行驗證

java Test
# 輸出:helloworld

JNI 核心記憶體管理鐵律

操作函數說明
Java→C 字串GetStringUTFChars分配本地記憶體,必須配對 Release
釋放字串ReleaseStringUTFChars歸還記憶體,否則洩漏
C→Java 字串NewStringUTF建立新 Java String 物件
陣列操作Get/ReleaseArrayElements同理需配對釋放

常見坑點與解決方案

  1. UnsatisfiedLinkError:庫名稱錯誤 (Windows 需 Test2.dll,載入時 loadLibrary("Test2"))、庫未在 java.library.path、32/64 位不匹配
  2. ClassFormatError:javah 作用於 .java 而非 .class 文件
  3. 記憶體洩漏:忘記呼叫 ReleaseStringUTFChars 或 ReleaseArrayElements
  4. 編碼問題:Java 內部 UTF-16,JNI 使用 Modified UTF-8,含補充字符需用 GetStringChars/NewString

JNI 開發流程總結

  1. 編寫含 native 方法的 Java 類 → javac 編譯
  2. javah 生成 .h 頭文件
  3. C/C++ 實現對應函數 → 編譯為動態庫 (.dll/.so)
  4. Java 運行時 System.loadLibrary 載入庫

掌握 JNI 能讓 Java 突破語言邊界,複用高效能 C/C++ 算法庫、系統級 API,是高階 Java 開發者必備技能。

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