Swing 桌面應用頻繁開關子視窗導致 `java.lang.OutOfMemoryError`,經 JProbe 8.0 深度分析,鎖定三大洩漏源頭:靜態集合持有引用、線程未正確終止、事件監聽器未解除註冊。本文完整記錄排查流程與修復方案。

現象:靜態 `Map` 未調用 `remove(key)`,鍵值對永久駐留
修復:
// 使用完畢後
map.remove(key); // 精確移除
map.clear(); // 清空整個 Map
map = null; // 釋放 Map 本身引用 (最徹底)
原則:靜態集合謹慎使用,必須有明確清理策略。
誤區:單純 `thread.join()` 等待不足以保證回收,若線程曾 `sleep()` 後 `join()` 可能卡住
正確模式:`interrupt()` + 開關變數 + `join()`
public void stopThread() {
try {
ifForceInterruptThread = true; // 開關變數
isThreadAlive = false;
logThread.t.interrupt(); // 打斷 sleep/wait
logThread.t.join(50); // 等待終止
} catch (InterruptedException ex) {
// 忽略
} finally {
controlList = null;
keyList = null;
logThread = null;
}
}
// 線程 run() 內部
try {
while (isThreadAlive) {
startMonitor();
Thread.sleep(interval);
}
} catch (InterruptedException e) {
if (!ifForceInterruptThread) { // 正常業務中斷 vs 強制關閉
// 記錄錯誤、嘗試重啟
}
}
現象:`JFrame` 子視窗 `dispose()` 後,匿名內部類監聽器仍被事件源持有
修復: