簡體   English   中英

BufferedImage.getGraphics()導致內存泄漏,是否有修復?

[英]BufferedImage.getGraphics() resulting in memory leak, is there a fix?

我遇到一些框架API調用BufferedImage.getGraphics()方法的問題,從而導致內存泄漏。 這個方法的作用是它總是調用BufferedImage.createGraphics()。 在Windows機器上,createGraphics()由Win32GraphicsEnvironment處理,它將偵聽器列表保存在其字段displayChanger中 當我在BufferedImage someChart上調用getGraphics時, someChart的SurfaceManager(保留對someChart的引用)被添加到Win32GraphicsEnvironment中的偵聽器映射中,從而防止someChart被垃圾收集。 之后沒有任何東西從偵聽器地圖中刪除someChart的SurfaceManager。

通常,一旦調用getGraphics,阻止BufferedImage被垃圾收集的匯總路徑如下:

GC Root - > localGraphicsEnvironment(Win32GraphicsEnvironment) - > displayChanger(SunDisplayChanger) - > listeners(Map) - > key (D3DChachingSurfaceManager) - > bImg(BufferedImage)

我本可以更改框架的代碼,以便在每次調用BufferedImage.getGraphics()之后,我保留對BufferedImage的SurfaceManager的引用。 然后,我獲取localGraphicsEnvironment,將其強制轉換為Win32GraphicsEnvironment,然后使用對BufferedImage的SurfaceManager的引用調用removeDisplayChangedListener()。 但我不認為這是解決問題的正確方法。

有人可以幫我解決這個問題嗎? 非常感謝!


更多細節和發現

我試圖添加到我的UI的組件每次重新繪制時都會調用BufferedImage.getGraphics()。 因此, displayChanger (在SunGraphicsEnvironment內部)保留的垃圾數量應隨着組件重新繪制而增長。

然而,事情表現得非常奇怪:

當我在我的UI上計算我的操作肯定會觸發重繪時,然后檢查displayChanger中的垃圾監聽器的數量與我的計數,它們不匹配。 (例如,在點擊之前有8位聽眾,我點擊了60次。畢竟,只有18位聽眾。)

另一方面,如果我打開斷點,並進入向displayListeners添加內容的過程,則每次單擊都會在displayListeners中生成一個新條目。 因此, displayListeners持有的每個BufferedImage 都會變成垃圾。

我認為可以共享或重用SurfaceManager作為displayListeners的鍵的可能性,但我的實驗排除了這種可能性。 我也考慮過緩存,我故意通過每次調用重繪獨特的方式來防止緩存發生。 不過,我不知道如何發生這種情況以及如何解決泄漏問題。

渲染BufferedImage ,應該在createGraphics()返回的圖形上下文中調用dispose() createGraphics() 這是一個示例和類似方法的列表

附錄:這似乎是一個稱為包裝的物體泄漏; 監聽器不匹配聽起來像使用調試器的工件。 您可以從Brian Goetz的文章“ 使用軟引用插入內存泄漏”中獲得一些想法。

當您不再需要圖像時,嘗試調用flush()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM