如何造成内存泄漏
這將是一個相當邪惡的職位-當您確實希望使某人的生活陷入困境時,您將在谷歌上搜索。 在Java開發領域,內存泄漏只是您在這種情況下會引入的錯誤類型。 為您的受害者保證幾天甚至幾周的辦公室不眠之夜。
我們將在這篇文章中描述兩次泄漏。 兩者都很容易理解和復制。 泄漏源于現實世界中的案例研究,但為清楚起見,我們提取了演示案例,以使您更短,更簡單。 但是請放心–在我們已經看到并修復了數百個泄漏之后–與演示的情況類似的情況比您預期的更普遍。
第一個闖入環的參賽者–臭名昭著的HashSet / HashMap解決方案,其中使用的鍵不具有或具有不正確的equals()/ hashCode( )解決方案。
當您執行上面的代碼時,您希望它可以永遠運行而不會出現任何問題-畢竟,內置的幼稚緩存解決方案應該只擴展到10,000個元素,然后停止增長,因為所有鍵都已經存在于HashMap中 。 但是,情況并非如此-元素會繼續添加,因為Key類在其hashCode()旁邊不包含適當的equals()實現 。 該解決方案很容易–與以下示例類似,添加equals()方法的實現,您很高興。 但是,在設法找到原因之前,您肯定已經失去了一些寶貴的腦細胞。
@Override public boolean equals(Object o) {boolean response = false;if (o instanceof Key) {response = (((Key)o).id).equals(this.id);}return response; }讓您的朋友保持清醒的第二個問題-一些操作中的字符串處理。 像魅力一樣工作,尤其是與JVM版本差異結合使用時。 在JDK 7u6中更改了 String內部構件的工作方式,因此,如果您設法找到僅次要版本導致生產和登臺不同的環境,那么您已經準備就緒 。 向您的朋友投擲類似于以下代碼的代碼,以進行調試,并想知道為什么問題不在生產中出現在其他任何地方。
class Stringer {static final int MB = 1024*512;static String createLongString(int length){StringBuilder sb = new StringBuilder(length);for(int i=0; i < length; i++)sb.append('a');sb.append(System.nanoTime());return sb.toString();}public static void main(String[] args){List<string> substrings = new ArrayList<string>();for(int i=0; i< 100; i++){String longStr = createLongString(MB);String subStr = longStr.substring(1,10);substrings.add(subStr);}} }上面的代碼中發生的事情–當它在預JDK 7u6上運行時,返回的子字符串在下面保留了對?1MB大字符串的引用。 因此,當使用-Xmx100m運行示例時,您將遇到意外的OutOfMemoryException。 將此與平臺差異結合起來,在您正在嘗試的環境中使用不同的JDK版本,第一批白發將蓬勃發展。 現在,如果您想掩蓋自己的足跡,我們可以將一些更高級的概念添加到產品組合中,例如
- 在其他類加載器中加載已損壞的代碼,并在丟棄原始類加載器后模仿類加載器泄漏 ,保留對加載的類的引用。
- 將有問題的代碼隱藏到finalize()方法中,使癥狀真正不可預測
- 將長時間運行的線程的棘手組合扔掉,這些線程將某些東西存儲在ThreadPool所訪問的ThreadLocals中–受控制的應用程序線程
希望我們能給您帶來一些思考,并為您下次生氣時提供一些技巧。 無數小時的核心調試保證。 除非您的朋友使用Plumbr ,否則當然會為他找到泄漏。 但是公然的市場營銷方面,我希望我們能夠在兩個簡單的例子中證明在Java中創建內存泄漏有多么容易。 你們中的大多數人都經歷了追蹤這樣一個錯誤的難度。 因此,如果您喜歡這篇文章,請訂閱我們的Twitter feed,以得到有關我們未來有關JVM性能調整的內容的警報。
翻譯自: https://www.javacodegeeks.com/2013/04/how-to-create-a-memory-leak.html
總結
- 上一篇: Spring Java配置
- 下一篇: wps中ppt的序号改(PPT幻灯片的编