首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 理論與實踐:良好的資源清理實踐——超越垃圾回收的必修課

     編輯:Java 程式設計入門

垃圾回收的誤區與現實

GC 只管記憶體(堆上物件)。檔案控制代碼、Socket、資料庫連線、鎖、訊號量等非記憶體資源必須顯式釋放,否則會導致資源耗盡、效能驟降甚至服務癱瘓。

核心原則:用完即釋,try-finally 守護

錯誤示範

// ❌ 若 props.load() 拋出異常,stream 永不關閉
public static Properties loadBadly(String file) throws IOException {
    FileInputStream stream = new FileInputStream(file);
    Properties props = new Properties();
    props.load(stream);
    stream.close(); // 異常時執行不到
    return props;
}

正確模式

// ✅ try-finally 確保釋放
public static Properties loadCorrectly(String file) throws IOException {
    FileInputStream stream = new FileInputStream(file);
    try {
        Properties props = new Properties();
        props.load(stream);
        return props;
    } finally {
        stream.close(); // 無論正常或異常都會執行
    }
}

關鍵: 資源取得放在 try 區塊外部,避免取得失敗進入 finally 導致 NullPointerException 掩蓋原始異常。

多重資源的嵌套地獄與 Java 7+ 解方

傳統嵌套寫法(JDBC 典型場景)

// ❌ 繁瑣、易漏、異常遮蔽風險高
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
    conn = dataSource.getConnection();
    stmt = conn.createStatement();
    rs = stmt.executeQuery(sql);
    // 處理 rs...
} finally {
    if (rs != null) try { rs.close(); } catch (SQLException ignore) {}
    if (stmt != null) try { stmt.close(); } catch (SQLException ignore) {}
    if (conn != null) try { conn.close(); } catch (SQLException ignore) {}
}

Java 7 try-with-resources(ARM)一行解決

// ✅ 自動按宣告逆序關閉、異常鏈保留、程式碼極簡
try (Connection conn = dataSource.getConnection();
     Statement stmt = conn.createStatement();
     ResultSet rs = stmt.executeQuery(sql)) {
    // 處理 rs...
}
  • 實作 AutoCloseable 的類別皆可用。
  • 關閉順序:rs → stmt → conn(宣告逆序)。
  • 若 close() 拋出異常,會被 suppressed exception 附加在主要異常上,不遮蔽原始錯誤。

Finalizer 不是救生圈

  • 執行時機不可預測(GC 觸發),資源釋放嚴重延遲。
  • JDK 9 標記 Object.finalize() 為 @Deprecated(forRemoval=true),未來將移除。
  • 永遠不要依賴 finalizer 釋放關鍵資源。

資源洩漏典型災難場景

資源洩漏後果典型原因
資料庫連線連線池耗盡、新請求掛起/失敗未在 finally 歸還、長事務未提交
檔案控制代碼「太多開啟檔案」、無法建立新檔流未關閉、臨時檔未刪
執行緒/執行緒池OOM、CPU 飆升、服務無回應任務未結束、關閉鉤子未註冊
鎖/訊號量死鎖、飢餓、吞吐量歸零未在 finally 釋放鎖

總結:資源管理鐵律

  1. 誰取得、誰負責釋放(Ownership 原則)。
  2. 盡早釋放,縮小資源佔用窗口。
  3. 統一用 try-with-resources(Java 7+),或 try-finally(舊版)。
  4. 實作 AutoCloseable 讓自訂資源納入標準管理。
  5. 監控與告警:連線池使用率、開啟檔案數、執行緒數納入觀測指標。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved