在移植 TinyLine SVG 示範程式至 NOKIA 3250 (S60 3rd FP1) 與 5700 (S60 3rd FP2) 時,發現執行緒優先級與異常處理差異導致完全不同的運行表現。本文記錄排查過程與核心發現。
| 裝置 | OS 版本 | 現象 |
| NOKIA 3250 | S60 3rd FP1 | 啟動後無任何回應,畫面靜止 |
| NOKIA 5700 | S60 3rd FP2 | 顯示等待畫面 → 跳出 "Error Internal Error" Alert → 黑屏 |
定位異常來源
在 MIDPSVGCanvas 的事件分發執行緒 run() 中捕獲到 Throwable 並彈出 "Internal Error":
public void run() {
Thread current = Thread.currentThread();
try {
while (current == thread) {
eventQueue.handleEvent(eventQueue.getNextEvent());
}
} catch (InterruptedException e) { return; }
catch (Throwable thr) {
thr.printStackTrace();
alertError("Internal Error"); // 此處被觸發
}
}
根因分析
- 執行緒優先級競爭: SVG 解析、渲染、事件分發等多執行緒同時搶佔 CPU,若事件分發執行緒優先級過低,長時間無法取得時間片,導致
getNextEvent() 異常或隊列溢位。
- 平台實作差異: 5700 (FP2) 的 JVM 對執行緒調度更嚴格,若事件執行緒非
Thread.NORM_PRIORITY,易觸發內部檢查拋出 Error(非 Exception,無法被 catch (Exception) 捕獲)。
- 3250 完全無回應: 推測為啟動執行緒死鎖或靜態初始化時觸發平台 Bug,導致主執行緒阻塞。
解決方案與最佳實踐
// 1. 明確設定事件分發執行緒優先級
Thread evtThread = new Thread(eventDispatcher);
evtThread.setPriority(Thread.NORM_PRIORITY); // 或略高於 NORM
evtThread.start();
// 2. 所有公開執行緒入口點捕獲 Throwable
public void run() {
try {
// 核心邏輯
} catch (Throwable t) { // 必須捕獲 Throwable
t.printStackTrace();
// 記錄至 RMS 或顯示友善錯誤訊息
}
}
// 3. 避免在事件分發執行緒執行耗時操作
// 解析、IO、複雜計算請派發至工作執行緒,完成後再 post 回事件執行緒刷新 UI
驗證結果
- 調整事件執行緒優先級為
NORM_PRIORITY+1 後,5700 不再彈出 Internal Error,SVG 正常渲染。
- 3250 問題需在靜態初始化階段加入
Thread.yield() 或延遲初始化策略繞過,屬個別平台 Bug。
結論
J2ME 多執行緒開發必須:明確設定優先級、捕獲 Throwable、縮短事件執行緒關鍵路徑。不同廠商/平台對執行緒調度實作差異大,實機測試不可省略。
- 上一篇文章: J2ME WTK 命令行編譯、預驗證、打包與執行完整指南
- 下一篇文章: J2ME 讀取文字資源檔:Unicode、UTF-8、Unicode Big Endian 三種編碼完整處理
Copyright ©
程式碼之家 All Rights Reserved