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

JNI Linux 平台開發指南:套件結構、中文路徑、陣列傳遞完整實作

     編輯:Java 相關知識

環境需求

  • JDK (含 javac, javah, java) 已安裝並設定 JAVA_HOME、PATH
  • GCC 工具鏈 (g++, make)
  • 目錄結構:

/JNI
├── com/yiluboke/zxy/WriteReadJ.java
└── WriteReadCpp/
    ├── writeReadDo.h
    ├── writeReadDo.cpp
    └── com_yiluboke_zxy_WriteReadJ.cpp

1. Java 類別定義 (WriteReadJ.java)


package com.yiluboke.zxy;

public class WriteReadJ {
    // 寫入檔案
    public native int writeFile(byte[] data, String filePath);
    
    // 檢查檔案可讀
    public native int readFilePre(String filePath);
    
    // 讀取檔案內容
    public native byte[] readFile(String filePath);
    
    static {
        System.loadLibrary("jniwritereadfile"); // 載入 libjniwritereadfile.so
    }
    
    public static void main(String[] args) { /* 測試碼 */ }
}

2. 編譯 Java 並產生 Header


cd /JNI
javac com/yiluboke/zxy/WriteReadJ.java
javah -jni com.yiluboke.zxy.WriteReadJ
# 產生 com_yiluboke_zxy_WriteReadJ.h

3. C++ 實作重點:中文路徑處理


// JNI 層轉換:jstring (UTF-16) → C 字串 (GB2312/UTF-8)
static const char* ENCODING = "GB2312"; // 或 UTF-8

char* Jstring2CStr(JNIEnv* env, jstring jstr, int* outLen) {
    jclass cls = env->FindClass("java/lang/String");
    jmethodID mid = env->GetMethodID(cls, "getBytes", "(Ljava/lang/String;)[B");
    jstring encoding = env->NewStringUTF(ENCODING);
    jbyteArray bytes = (jbyteArray)env->CallObjectMethod(jstr, mid, encoding);
    
    jsize len = env->GetArrayLength(bytes);
    *outLen = len + 1;
    jbyte* elems = env->GetByteArrayElements(bytes, JNI_FALSE);
    
    char* result = new char[len + 1];
    memcpy(result, elems, len);
    result[len] = '\0';
    
    env->ReleaseByteArrayElements(bytes, elems, JNI_ABORT);
    return result; // 呼叫端負責 delete[]
}

4. 陣列傳遞:Java byte[] ↔ C++ byte*


// Java → C++ (寫入)
JNIEXPORT jint JNICALL Java_com_yiluboke_zxy_WriteReadJ_writeFile(
    JNIEnv* env, jobject, jbyteArray jData, jstring jPath) {
    
    int pathLen;
    char* path = Jstring2CStr(env, jPath, &pathLen);
    jbyte* data = env->GetByteArrayElements(jData, JNI_FALSE);
    jsize len = env->GetArrayLength(jData);
    
    int ret = writeFile((BYTE*)data, len, path);
    
    env->ReleaseByteArrayElements(jData, data, JNI_ABORT);
    delete[] path;
    return ret;
}

// C++ → Java (讀取)
JNIEXPORT jbyteArray JNICALL Java_com_yiluboke_zxy_WriteReadJ_readFile(
    JNIEnv* env, jobject, jstring) {
    
    jbyteArray arr = env->NewByteArray(g_len);
    env->SetByteArrayRegion(arr, 0, g_len, (jbyte*)g_buffer);
    return arr;
}

5. 編譯產生 .so


g++ -fPIC -shared -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux \
    writeReadDo.cpp com_yiluboke_zxy_WriteReadJ.cpp \
    -o libjniwritereadfile.so
  • -fPIC:位置無關程式碼 (共享庫必須)
  • -shared:產生動態連結庫
  • 輸出檔名**必須**為 lib<name>.so,System.loadLibrary("name") 會自動加前綴

6. 設定 Library Path 執行


export LD_LIBRARY_PATH=/JNI:$LD_LIBRARY_PATH
java com.yiluboke.zxy.WriteReadJ

或修改 /etc/profile 永久生效。

7. 完整 Demo 下載

百度網盤:JNI Linux Demo

總結

Linux JNI 關鍵點:**命名規範 (libxxx.so)、編碼轉換 (getBytes 指定編碼)、陣列釋放模式 (JNI_ABORT/0/COMMIT)、LD_LIBRARY_PATH 設定**。掌握這些即可跨平台開發高效能原生介面。

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