javac, javah, java) 已安裝並設定 JAVA_HOME、PATHg++, make)
/JNI
├── com/yiluboke/zxy/WriteReadJ.java
└── WriteReadCpp/
├── writeReadDo.h
├── writeReadDo.cpp
└── com_yiluboke_zxy_WriteReadJ.cpp
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) { /* 測試碼 */ }
}
cd /JNI
javac com/yiluboke/zxy/WriteReadJ.java
javah -jni com.yiluboke.zxy.WriteReadJ
# 產生 com_yiluboke_zxy_WriteReadJ.h
// 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[]
}
// 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;
}
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") 會自動加前綴
export LD_LIBRARY_PATH=/JNI:$LD_LIBRARY_PATH
java com.yiluboke.zxy.WriteReadJ
或修改 /etc/profile 永久生效。
百度網盤:JNI Linux Demo
Linux JNI 關鍵點:**命名規範 (libxxx.so)、編碼轉換 (getBytes 指定編碼)、陣列釋放模式 (JNI_ABORT/0/COMMIT)、LD_LIBRARY_PATH 設定**。掌握這些即可跨平台開發高效能原生介面。