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

Eclipse 圖片資源管理深度解析:從 SWT 到 JFace 最佳實踐

     編輯:Java 相關知識

目錄

  1. 系統資源基礎
  2. SWT 圖片資源管理
  3. Display Hook 銷毀機制
  4. JFace ImageDescriptor
  5. JFace ImageRegistry 與 ResourceManager
  6. ImageRegistry 適用場景與使用規則
  7. Eclipse 外掛共享圖片機制
  8. 實戰經驗總結

一、系統資源基礎

Java 開發者使用 SWT/JFace 時,無法完全依賴 JVM 垃圾回收釋放系統資源(JVM 僅能釋放記憶體中的資源句柄引用物件)。SWT 中系統資源基底類別 org.eclipse.swt.graphics.Resource 明確要求:「應用程式建立的資源必須自行 dispose」。這也是「誰建立,誰負責」原則的由來,適用於 Image、Font、Color、GC 等所有系統資源。

系統資源洩漏會導致 org.eclipse.swt.SWTError: No more handles,嚴重時造成應用程式崩潰,罪魁禍首往往是未正確釋放資源的程式碼。

二、SWT 圖片資源管理

org.eclipse.swt.graphics.Image 文件明確指出:「應用程式必須明確呼叫 Image.dispose() 釋放作業系統資源」。ImageData 可視為 Image 的中繼資料模型,描述建立 Image 所需資訊。

SWT 僅提供一條路徑:自行覆寫元件的 dispose() 方法釋放資源。若覺得不夠靈活,請看下一節 Display Hook 機制。

三、Display Hook 銷毀機制

Display 提供 disposeExec(Runnable) 註冊自定義執行緒,在 Display.release() 時回呼:

display.disposeExec(new Runnable() {
    public void run() {
        image.dispose();
        // 其他資源釋放邏輯
    }
});

這正是 JFace ImageRegistry、ResourceManager 能確保 Display 釋放時徹底清理資源的基礎。

SWT 資源釋放兩大路徑總結

  1. 覆寫元件 dispose():Display 運行期間即可釋放,最佳方式。
  2. Display Hook 機制:確保 Display 釋放時清理,但不要過度依賴,因可能在釋放前已發生資源耗盡崩潰。

四、JFace ImageDescriptor

JFace 提供 ImageDescriptor 工廠類別建立圖片,兩種方式:

  • createImage():每次建立全新 Image,呼叫者必須自行 dispose。
  • createResource():使用快取復用機制,回傳共享 Image。完成使用後必須呼叫 destroyResource() 而非直接 dispose Image。

差異分析:

  1. createImage 每次建立新資源,耗效能。
  2. createResource 快取復用提升效能,但未解決釋放責任,反而易造成誤以為無需管理而洩漏。

孤立使用 ImageDescriptor 時,開發者仍須自行管理釋放(覆寫元件 dispose 或 Display Hook)。

五、JFace ImageRegistry & ResourceManager

JFaceResources 為資源管理外觀類別,取得 ImageRegistry 時會自動向 Display 註冊 Hook:

public static ResourceManager getResources(final Display toQuery) {
    ResourceManager reg = (ResourceManager) registries.get(toQuery);
    if (reg == null) {
        final DeviceResourceManager mgr = new DeviceResourceManager(toQuery);
        toQuery.disposeExec(new Runnable() {
            public void run() {
                mgr.dispose();
                registries.remove(toQuery);
            }
        });
    }
    return reg;
}

DeviceResourceManager 對 DeviceResourceDescriptor (ImageDescriptor) 進行引用計數管理:

  • create(descriptor):首次註冊建立引用計數並 allocate 資源快取;後續增加計數回傳快取資源。
  • destroy(descriptor):計數歸 1 時徹底銷毀;大於 1 時遞減計數(資源保留)。

ImageRegistry 核心操作與管理策略

put(String key, Image image)           // 註冊 Image,自行管理引用計數
put(String key, ImageDescriptor descriptor) // 註冊 Descriptor,委託 ResourceManager 管理
Image get(String key)
ImageDescriptor getDescriptor(String key)
remove(String key)                     // 取消註冊
dispose()                              // 銷毀資源

結論:

  1. 註冊 ImageDescriptor 完全委託 ResourceManager 管理與銷毀(在 ResourceManager.dispose() 中)。
  2. 註冊 Image 則由 ImageRegistry 以內部類 OriginalImageDescriptor 包裝管理引用計數,銷毀在自身 dispose() 完成(已 Hook 到 Display 釋放流程)。
  3. ImageRegistry 不希望使用者手動干預釋放,提供 remove() 取消註冊即可。

六、ImageRegistry 適用場景與使用規則

適用場景

  1. 高度共享、高頻使用的圖片資源:不急於銷毀,利用快取優勢與 Display Hook 確保釋放。
  2. 自行管理 ImageRegistry 實例:復用管理功能建立自訂快取策略,但必須在適當時機呼叫 dispose()。Eclipse Workbench shared images 即採此模式。

使用規則

  1. 誰建立,誰負責:資源建立由 ImageRegistry 負責,使用者不應干預釋放。共享資源釋放會影響其他使用者。熟悉原理者可參與引用計數管理間接參與釋放。
  2. 非共享、局部、低頻資源勿託管給 ImageRegistry:反而延遲釋放至 Display 釋放時,造成資源佔用。
  3. 嚴格管理 Key 值:ImageRegistry 本質是全域物件,Key 管理混亂會導致衝突。

七、Eclipse 外掛 Shared Images 機制

外掛暴露圖片資源供其他外掛使用:

  1. 定義 ISharedImages 介面提供語意化 Key
  2. 實作介面結合 ImageRegistry 管理,提供公開 dispose()
  3. 在 plugin.xml 暴露 ISharedImages
  4. 外掛停止 (stop()) 時呼叫 dispose() 釋放資源

使用方:PlatformUI.getWorkbench().getSharedImages().getImage(key),絕不參與釋放,遵循「誰建立,誰負責」。

八、實戰經驗總結

  1. 堅持「誰建立,誰負責」:
    • 自建資源:覆寫元件/LabelProvider dispose() 釋放(適合局部資源);或 Display Hook(長期資源)。
    • JFaceResources.getImageRegistry():勿自行釋放,讓 Registry 管理(適合全域高頻共享資源)。
    • ISharedImages:提供方負責釋放,參考 Workbench 實作。
  2. 正視資源洩漏兩大成因:
    • 未釋放導致洩漏
    • 釋放過晚(如局部資源錯誤託管給 Registry)導致累積過多
  3. 關注建立/銷毀效能:善用 ImageDescriptor.createResource() 替代 new Image() 減少頻繁建立銷毀開銷;長期資源用 Registry。
  4. 特殊場景自訂管理策略:參考 JFace 原理自行實作,優化團隊適用度、降低誤用風險。
  5. 使用前必讀 API 與原始碼:大型外掛產品圖片管理極重要;簡單開發遵循基本原則即可,新手勿濫用 Registry 增加複雜度。

註:文章趕工產出,若有錯誤歡迎指正。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved