KVM 不支援標準 JNI 機制。若需新增系統級 API(如存取硬體、平台專有服務),必須直接修改 KVM 內部核心代碼。不同 J2ME 裝置擁有不同的系統調用集合,本文以 Sun 官方 KVM 源碼為基礎,示範新增 org.test.MiniTest.TestInt() 並返回 9999 的完整流程。
classes.zip 中新增包含 native 方法的類nativeCore.c 實現對應的 Native 函數路徑:J2ME_cldc/api/org/test/MiniTest.java
package org.test;
public class MiniTest {
public static native int TestInt();
}
cd J2ME_cldc\build\win32
make
編譯會在鏈接階段報錯:undefined symbol _Java_org_test_MiniTest_TestInt。原因:Java 層宣告了 native 方法,但 C 層尚未實現。
編譯過程中,jcc 會根據 classes.zip 自動生成 ROMJavaWin.c,其中聲明:
extern void Java_org_test_MiniTest_TestInt(void);
編輯 nativeCore.c,新增:
void Java_org_test_MiniTest_TestInt(void) {
pushStack(9999);
}
為何用 pushStack? Java 位元組碼基於堆疊機器模型,返回值必須壓入運算堆疊。pushStack 是 KVM 內部巨集,將整數推入堆疊頂供 Java 端取用。詳細原理請參考《Inside Java Virtual Machine》第「堆疊幀與運算堆疊」章節。
make
import org.test.*;
class Test {
public static void main(String[] args) {
System.out.println("TestResult=" + MiniTest.TestInt());
}
}
編譯與運行:
# 需將 J2ME_cldc/classes.zip 複製到測試目錄
javac -classpath classes.zip Test.java
kvm -classpath . Test
輸出:TestResult=9999 ✓
Java_包名_類名_方法名(包名以底線分隔),不可變更。pushStack/popStack 等巨集封裝了堆疊操作。為 KVM 新增系統 API 的本質是「Java 宣告 + C 實現 + 堆疊協定」的三位一體。掌握此流程,即可為特定嵌入式平台打造專屬的底層能力集,突破標準 API 的限制。