Java Native Interface (JNI) 讓 Java 呼叫 C/C++ 成為可能,但其設計綁定 C 語言,帶來諸多痛點:
JNIEnv* 執行緒綁定、區域/全域參考管理、異常檢查與清理全靠手工ExceptionOccurred()、ExceptionClear()、轉換為 C 錯誤碼Get/SetArrayElements ,物件欄位/方法存取需字串簽名Jace (Java And C++ Engine) 是開源工具包,透過 C++ 代理類 封裝 JNI,提供:
| 特性 | 說明 |
|---|---|
| 編譯期類型安全 | C++ 代理類對應 Java 類,編譯器捕獲類型錯誤 |
| 自動代理生成 | 從 .class/.jar 自動生成 .h/.cpp,支援批次處理 |
| 異常透明傳遞 | Java 異常自動轉為對應 C++ 代理異常,支援 try-catch |
| 執行緒與參考自動管理 | 自動 AttachCurrentThread、全域參考生命週期管理 |
| C++ 標準庫整合 | String 支援 +、==、ostream <<;陣列支援 STL 風格迭代 |
| 模板化類型安全陣列 | JArray<T> 統一陣列操作,編譯期檢查元素類型 |

// 9 大基本類型一一對應
JBoolean, JByte, JChar, JShort, JInt, JLong, JFloat, JDouble, JVoid
// 使用範例:自動拆裝箱
JInt hashCode = String("A String").hashCode(); // 直接呼叫,自動轉換
JArray buffer(512); // 模板化陣列建立
JValue:所有代理基類,持有 jvalue 與 JClassJClass:對應 jclass,提供方法/欄位 ID 快取JObject:所有引用類型基類,管理全域參考生命週期
jobject(JNI 傳入參數)DeleteGlobalRefisNull() 檢測空參考JString、JThrowable 等核心類別深度整合 C++
// 開發者無需關心 JNIEnv* 與 AttachCurrentThread
// Jace 內部每個函數自動:
// 1. 獲取當前執行緒的 JNIEnv*
// 2. 若未附加 JVM,自動 AttachCurrentThread
// 3. 使用全域參考,跨執行緒安全
using namespace jace::java::net;
void readGoogle() {
try {
URL url("https://www.google.com"); // 內部 NewObject 失敗拋 MalformedURLException
} catch (MalformedURLException& e) { // 直接捕獲 C++ 代理異常
cout << e << endl; // 支援 ostream 輸出
}
}
// Jace 內部:檢查 ExceptionOccurred → ExceptionClear → 建立對應 C++ 代理異常 → throw
using jace::javax::swing::JFrame;
JFrame createFrame(const std::string& title, int x, int y) {
JFrame frame(title); // std::string → java.lang.String 自動轉換
frame.setLocation(x, y); // int → JInt 自動轉換
return frame;
}
// Java 端
public class Foo {
public int aField;
public String aMethod(URL url);
}
// C++ 端:同名方法存取欄位,呼叫語法一致
Foo foo;
foo.aField() = 14; // 存取 public 欄位
String result = foo.aMethod(URL("https://google.com")); // 呼叫方法
JArray intArray(10); // 呼叫 NewIntArray
int val = intArray[2]; // 呼叫 GetIntArrayElements + 索引
JArray strArray(5); // 呼叫 NewObjectArray
std::string s = strArray[2]; // 呼叫 GetObjectArrayElement + 自動轉 std::string
| 工具 | 用途 | 輸出 |
|---|---|---|
| ProxyGen | 單一 .class 檔生成代理 | 標準輸出 .h/.cpp |
| BatchGen | 整個 .jar/.zip 批次生成 | 指定目錄下的 .h/.cpp |
# ProxyGen 用法
ProxyGenerator MyClass.class header|source [-protected] [-package] [-private]
# BatchGen 用法
BatchGenerate rt.jar ./include ./src [-protected] [-package] [-private]
java.lang.Object 新增 operator<<(ostream&, Object&),支援 cout << objjava.lang.String 新增 operator+、operator=、operator==,與 std::string/char* 無縫互操作begin()/end(),可用於範圍 for 迴圈std::for_each 等演算法,相容 STL 容器概念JNI 的痛苦根源在於「C 語言綁定」。Jace 以現代 C++ 封裝 JNI,提供類型安全、異常透明、資源自管、語法友善的原生整合體驗。對於需高效能呼叫 C++ 庫、嵌入 JVM 於 C++ 應用、開發高效能混合系統的團隊,Jace 是從 JNI 地獄走向生產力天堂的關鍵橋樑。