public class Runtime {
private static Runtime currentRuntime = new Runtime();
public static Runtime getRuntime() {
return currentRuntime;
}
private Runtime() {}
public void exit(int status) {
throw new SecurityException(
"MIDP lifecycle does not support system exit.");
}
public native long freeMemory();
public native long totalMemory();
public native void gc();
}
private static Runtime currentRuntime = new Runtime(); 類載入時即建立唯一實例。private Runtime() 禁止外部實例化。getRuntime() 全域存取點,無雙重檢查鎖、無同步開銷 (類載入天然線程安全)。| 方法 | 含義 | J2ME 實務用途 |
|---|---|---|
freeMemory() | 當前可用堆位元組數 | 載入大資源前檢查、決定是否執行 gc()、記憶體洩漏監控 |
totalMemory() | JVM 當前向 OS 申請的總堆大小 | 觀察堆擴張行為、估算剩餘擴張空間 |
gc() | 請求垃圾回收 (非強制) | 場景切換前主動調用、大物件釋放後嘗試回收 |
注意:CLDC 無 maxMemory(),最大堆大小由裝置廠商固定 (通常 200KB~2MB),不可動態調整。
exit() 拋出 SecurityException:揭示「無進程模型」public void exit(int status) {
throw new SecurityException("MIDP lifecycle does not support system exit.");
}
這行代碼揭示了 J2ME 與桌面/伺服器 Java 的根本架構差異:
| 特性 | Java SE (桌面/伺服器) | Java ME (MIDP/CLDC) |
|---|---|---|
| 進程概念 | 有,JVM = 一個 OS 進程 | 無,MIDlet = 容器內組件 |
| 啟動方式 | java MainClass 新建進程 | AMS (Application Management System) 在現有 JVM 中載入類、呼叫 startApp() |
| 退出方式 | System.exit() / Runtime.exit() 終止進程 | 調用 notifyDestroyed() 通知 AMS,AMS 回收資源、呼叫 destroyApp() |
| 多任務 | 多進程/多線程 | 單一 JVM 同一時間只跑一個 MIDlet (MIDP 2.0 允許後台但受限) |
| 類載入隔離 | ClassLoader 隔離 | 無自訂 ClassLoader,所有 MIDlet 共享同一 Bootstrap ClassLoader |
System.exit() 無意義,因為沒有「進程」可終結。public class MyMidlet extends MIDlet {
public void startApp() {
// 初始化 UI、資源、網路
}
public void pauseApp() {
// 釋放非必要資源、暫停執行緒
}
public void destroyApp(boolean unconditional) {
// 釋放所有資源、關閉連線、存檔
if (unconditional || canSaveState()) {
notifyDestroyed(); // 告訴 AMS 我已準備好被銷毀
} else {
throw new MIDletStateChangeException("User cancelled exit");
}
}
}
永遠不要在 MIDlet 中呼叫 Runtime.getRuntime().exit(),只會得到 SecurityException 且無法優雅退出。
java.lang.Runtime 在 J2ME 中被精簡為「單例門面 + 記憶體查詢 + GC 請求」,其 exit() 方法直接拋出異常,強制開發者面對「無進程、AMS 托管生命週期」的嵌入式現實。理解這一點,是從桌面 Java 思維轉型為行動/嵌入式 Java 思維的關鍵一步。