11

這是我的用例。我們試圖縮小應用程序中潛在的內存泄漏,並且我們使用內存分析工具對堆進行快照,以便查找對象實例和引用。 (如果有幫助,我們正在使用YourKit。)有沒有辦法在Java中強制弱引用對象和/或軟引用對象進行GC化?

此應用程序廣泛使用動態代理和CGLIB代理,最終在WeakHashMaps中存儲大量對類和類加載器的引用。

在我們的測試用例運行之後,我們期待所有對對象X及其類加載器的硬引用都會消失,但由於最後有很多代理參與測試用例,我們有許多弱/軟引用留給它。 (我只能找到WeakHashMap引用,但YourKit將弱引用和軟引用包含在摘要中的一個行項目中,所以我不能確定我不會在某處丟失軟引用。)

即使在從JVM請求完整的GC。 (在服務器模式下使用sun 1.6.0_23 JDK。)

似乎好像JVM承認只有對這些對象的弱/軟引用,但我無法強制它將GC這些東西百分百肯定。 (所以,我想要的是,它完全從堆中消失,並且它的類加載器使用permgen也消失。)

任何人都知道配置和/或強制JVM僅處理對象的方式/弱引用?

+0

你有沒有任何機會註冊對象的全球性事件?也許一個靜態字段(或其他線程對象或別的東西),有給他們一個參考... – Mehrdad

+0

好問題 - 已經調查了這一點,並YourKit提供足夠的信息來快速找到這些事情。雖然我仍然在調查,到目前爲止,我已經縮小下來(我認爲)由Spring的AOP引發一些行爲時,它所代理使用RegexpMethodPointcutAdvisor可以類/方法。然而,這只是這位顧問的一個特例(迄今爲止) - 我們在許多地方使用這個看起來並沒有造成這個問題的地方。仍在努力確定一個案件的獨特之處......當我擁有更多案件時將會回傳。 – Scott

+0

好吧,這是更新。我相信我找到了針對我特殊問題的吸菸槍。在我們的應用程序中使用的一個代理懶惰地從緩存中加載它的實現,以確保操作始終發生在最近緩存的對象上。如果緩存沒有該對象,則緩存已配置爲實例化並初始化該對象。代理是一個相當愚蠢的代理,對於任何方法調用,它會向對象請求緩存,然後調用對象上的方法。評論有一個字符的限制,因此,閱讀... – Scott

回答

10

調用GC應始終釋放所有弱可到達對象(假設「請求」通過調用System.gc取得實際授予)。如果弱引用未被GC清除,則意味着對象至少可以輕鬆訪問。

清除軟引用是棘手的,因爲這是到JVM的自由裁量權。保證清除可輕鬆訪問的對象的唯一方法是導致引發OutOfMemoryError。這個技巧在this discussion中得到證明。

+1

是不是'System.gc'只是一個提示?因此不是對「否」這個問題的回答嗎? – nmr

+1

我不知道這是否適用於Dalvik/ART – nmr

相關問題