WebSphere Real Time 即時 Java 應用開發完整指南
IBM WebSphere Real Time 解決標準 Java 不確定性問題,在 Linux RT + BladeCenter 硬體上提供微秒級延遲、確定性 GC、可預測執行。本文涵蓋 Metronome GC 優勢、AOT 預編譯、NHRT 非堆記憶體程式設計、Sweet Factory 完整實戰案例。
即時系統核心需求
- 低延遲:有限時間內響應訊號
- 確定性:無 GC 無限暫停
- 可預測性:執行緒優先級管控、執行時間一致
- 無優先級反轉:高優先級執行緒不被阻塞
- 物理記憶體存取:裝置驅動程式等需求
Metronome GC 確定性優勢驗證
Lunar Lander 模擬案例:
- 控制器依雷達脈衝回波計算著陸器位置
- GC 暫停導致位置測量錯誤 → 墜毀風險
標準 JVM 執行結果

藍線 (雷達測量) 出現嚴重尖峰,對應 GC 暫停,導致位置誤差。
WebSphere Real Time + Metronome 執行結果

無明顯尖峰,每次安全著陸。
GC 詳細統計 (-verbose:gc)
<gc type="heartbeat" id="2" intervalms="1002.940">
<summary quantumcount="171">
<quantum minms="0.006" meanms="0.470" maxms="0.656" />
<heap minfree="142311424" meanfree="171371274" maxfree="264060928" />
<immortal minfree="15964488" meanfree="15969577" maxfree="15969820" />
</summary>
</gc>
- 1 秒內 171 個量子
- 平均暫停 0.470 毫秒,最大 0.656 毫秒
TuningFork 分析工具視覺化

AOT 預編譯消除 JIT 不確定性
生成預編譯代碼
jxeinajar -Xrealtime -outPath aotJarPath
輸出:預編譯 3,098/3,106 方法,產生 JXE 格式 JAR
識別預編譯 JAR
jar vtf demo.jar
# 預編譯 JAR 包含 .class 佔位符與 jxe*******.class
# 一般 JAR 僅含 .class 檔案
執行預編譯應用
java -Xrealtime -Xnojit -classpath aotJarPath AppName
-Xnojit:禁用 JIT,強制使用 AOT 代碼
-Xrealtime:啟用即時 JVM
系統 JAR 同步預編譯
java -Xrealtime -Xnojit \
-Xbootclasspath/p:aotSystemJarPath/core.jar:aotSystemJarPath/vm.jar:aotSystemJarPath/realtime.jar \
-classpath aotJarPath/realTimeApp.jar realTimeApp
/p 參數前置掛載至 Bootstrap Classpath,確保優先載入。
驗證預編譯載入
-verbose:relocations # 印出重定位資訊
-verbose:class # 印出類別載入
-verbose:dynload # 印出動態載入詳情
# 組合使用:-verbose:class,dynload
# 出現在 class 但不在 dynload = 已預編譯
Profile-Guided AOT 編譯
# 1. 執行應用收集熱門方法
java -Xjit:verbose={precompile},vlog=optFileName -classpath appJarPath realTimeApp
# 2. 依配置檔選擇性預編譯
jxeinajar -Xrealtime -outPath aotJarPath -optFile optFileName
NHRT (NoHeapRealtimeThread) 非堆記憶體程式設計
RTSJ 記憶體區域
| 區域 | 特性 | GC 管理 | 適用場景 |
| Heap | 標準 Java 物件 | 是 | 一般應用 |
| Immortal Memory | 永不回收,應用存活期持續存在 | 否 | 長期共享物件、類別資料 |
| Scoped Memory | 進入範圍存在,離開釋放,引用計數管理 | 否 | 短期任務、可預測大小分配 |
Sweet Factory 案例架構


核心設計決策
- 輪詢執行緒 (NHRT, 優先級 38):Immortal Memory 啟動,預建 Scoped Memory 區域
- 分揀池 (NHRT, 優先級 37):Immortal Memory,堆疊原始值計算,需要時進入 Scoped Memory 呼叫 WorkerConsole
- 稽核記錄 (標準 Thread, 優先級 5):Heap 記憶體,處理字串/I/O
- 跨執行緒通訊:WaitFreeReadQueue (多讀單寫) + 同步控制單一 NHRT 讀取
- 物件重用池:Immortal Memory 預建 Measurement 物件循環重用,避免洩漏
關鍵程式設計模式
// Context 檢查斷言
assert ContextChecker.checkContext(ContextChecker.NHRT_IMMORTAL);
// 錯誤處理預分配
Runnable errorHandler = new ErrorReportingRunnable(); // 建構時預分配
ScopedMemory errorScope = new LTMemory(ERROR_SCOPE_SIZE); // 預留錯誤處理空間
// 執行緒啟動樣板
Bootstrapper.runInArea(ImmortalMemory.instance(), () -> {
new PollingThread(productionLine).start();
});
Sweet Factory 專案建構與執行
建構腳本 (build.sh)
#!/bin/bash
mkdir -p bin
javac -d bin src/**/*.java
jar cfm sweetfactory.jar MANIFEST.MF -C bin .
jxeinajar -Xrealtime -outPath aot sweetfactory.jar
執行指令與參數
# 預設參數:60秒、3條產線、20ms間隔
java -Xnojit -Xrealtime -jar sweetfactory.jar
# 高負載測試:60秒、50條產線、10ms間隔、60MB Scoped Memory
java -Xnojit -Xrealtime -Xgc:scopedMemoryMaximumSize=60M -jar sweetfactory.jar 60 50 10
執行結果範例
Starting demo
1173021249509: Jar 32 overfilled
1173021250228: Jar 139 underfilled
...
Run summary:
Production line stats:
Line # Sweet Type Jar Type # Missed Max Pool Min Pool
0 Giant Gobstoppers Large 0 10 7
Total missed jars: 0
Measurement pool min depth: 391
Audit max queue depth: 5
Total processed: 8998
負載極限測試
- ~70 條產線 / 10ms 間隔為系統極限
- 超載現象:
Error: measurement pool exhausted、Missed 20 jars!
- CPU 耗盡導致 Metronome 與稽核執行緒無法執行,池耗盡
實戰提示與技巧總結
- Context 斷言:每關鍵點檢查執行緒類型與記憶體區域
- 錯誤處理預分配:Runnable + Scoped Memory 預備,避免 OOM 時無法報錯
- 避免 Heap/Non-Heap 鎖共享:使用 WaitFreeQueue 隔離同步
- 文檔化架構決策:非堆程式碼極難閱讀,必須詳細註解記憶體區域切換邏輯
結語
WebSphere Real Time 提供兩條路徑:
1. Metronome GC:多數軟即時需求,標準 Java 程式模型,毫秒級確定性
2. NHRT + 非堆記憶體:硬即時極致響應,但開發複雜度指數級上升,最佳實踐失效
選擇取決於確定性需求等級與團隊技術承接能力。
- 上一篇文章: Java 字元編碼入門(一):Unicode 與 UCS 歷史恩怨與標準演進
- 下一篇文章: 即時 Java 第 4 部分:即時垃圾收集 - Metronome GC 深度解析
Copyright ©
程式碼之家 All Rights Reserved