簡體   English   中英

如何在堆轉儲中的異常實例沒有入站引用的情況下調試內存泄漏?

[英]How to debug memory leak where exception instances in heap dump have no inbound references?

我一直在嘗試診斷我正在編寫的Android應用程序中的內存泄漏。 我有一個堆轉儲加載到Eclipse中,但我看到的結果非常好奇。 堆中有大約20,000個異常實例(特別是來自UnboundID LDAP庫的LDAPException),沒有入站引用。

也就是說,它們出現在支配者樹的根部。 OQL SELECT objects e FROM com.unboundid.ldap.sdk.LDAPException e WHERE (inbounds(e).length = 0)返回超過20,000個結果,總計幾乎所有堆。 然而,GC在堆轉儲之前運行,我可以看到它在執行泄漏代碼期間反復運行在控制台中。 如果這些實例沒有入站參考,那么可以讓它們保持活力?

我也嘗試過“最短的GC路徑”查詢。 它顯示了一個保留2個實例的LDAPConnectionReader行,以及具有各種十六進制地址的~20k LDAPException @ <addr> unknown行。

更新 :自發布以來我沒有時間進一步診斷這個問題,我發布的獎金在我可能會結束之前結束。 我現在盡可能地獎勵它,以免浪費點數。 感謝所有關注此事的人! 我將稍后回來並再次更新進一步診斷的結果,當生活稍微忙碌時。

無論這些異常是否被拋出,就內存使用而言,這個細節都是無關緊要的。

雖然您希望在堆轉儲中看到誰擁有引用,但由於某種原因,您無法實現此目的。 我想知道本機代碼是否會在堆轉儲工具中得到正確的符號化?

無論哪種方式,作為嘗試的新事物,我建議不要調試拋出這些異常但創建它們的位置。 在類和/或其所有構造函數上放置斷點。 理想情況下,您只是從堆轉儲引用中獲取此信息,但如果您可以看到誰重復構建這些對象,它仍然可以證明是有用的......我猜它們來自同一個地方。

如果您使用的是Eclipse,則可以在LDAPException上添加斷點。 在這里,您可以找到有關如何設置一個的教程: Eclipse提示:異常斷點

只要拋出所選類型的異常,這些斷點就會暫停執行。 一旦找到引發如此多異常的條件,就可以修復bug。

它並沒有完全調試為什么未引用的異常填滿堆,但我希望它可以幫助。

我不熟悉OQL,特別是Android平台,或者該平台上Java GC的內部工作原理,但對我來說最明顯的是缺少的LDAPException元數據。 它有錯誤代碼,消息,方法等......它在哪里? 這是未初始化的嗎? 你有沒有發布所有這些東西? 像服務器重定向到自身的東西可能讓我說“哦,這很奇怪,但它有點意義。”

您是否嘗試過將此lib替換為JDK 看起來如果可能的話應該很容易。

然后我會開始擠壓它所有的東西。 GC特征可以提供線索。 是否存在以某種方式逃避收集的實例? 每秒創建多少? 每次通過gc'd會有多少陳舊的,或者它是不變的? 他們是在像Danny談論的忙碌循環中創建的嗎? 如果你在繁忙的循環中調用System.gc()怎么辦?

但是,是的,我開始打印調試。 希望有更好的解決方案。 :-P

暫無
暫無

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

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