編寫Java代碼制作一個內存溢出的情形。本站提示廣大學習愛好者:(編寫Java代碼制作一個內存溢出的情形)文章只能為提供參考,不一定能成為您想要的結果。以下是編寫Java代碼制作一個內存溢出的情形正文
這將會是一篇比擬險惡的文章,當你想在某小我的生涯中制作喜劇時你能夠會去谷歌搜刮它。在Java的世界裡,內存溢出僅僅只是你在這類情形下能夠會引入的一種bug。你的受益者會在辦公室裡渡過幾天乃至是幾周的不眠之夜。
在這篇文章中我將會引見兩種溢出方法,它們都是比擬輕易懂得和重現的。而且它們都是起源實際項目標案例研討,然則為了讓你清楚地控制,我把它們簡化了。
不外寧神,在我們碰到息爭決了很過溢出bug以後,相似的案例將會比你想象得加倍廣泛。
先來一個進入狀況的,在應用HashSet/HashMap時,所用鍵值沒有或許其equals()/hashCode()辦法不准確,這會招致一個污名昭著的毛病。
class KeylessEntry { static class Key { Integer id; Key(Integer id) { this.id = id; } @Override public int hashCode() { return id.hashCode(); } } public static void main(String[] args) { Map m = new HashMap(); while (true) for (int i = 0; i < 10000; i++) if (!m.containsKey(i)) m.put(new Key(i), "Number:" + i); } }
當你運轉下面的代碼時,你能夠會希冀它運轉起來永久不會出成績,究竟內置的緩存計劃只會增長到10,000個元素,然後就不會再增長了,一切的key都曾經湧現在 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; }
下一個你得提示同伙的是和String處置相干的操作。它的表示會很詭異,特殊是聯合JVM版本差別的時刻。String的外部任務機制在 JDK 7u6中被轉變了,所以假如你發明產物情況只是小版本號的差別,那末你曾經預備好前提了。把相似上面的代碼給你的同伙調試,然後問他為何這個bug只會在產物中湧現。
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 substrings = new ArrayList(); for(int i=0; i< 100; i++){ String longStr = createLongString(MB); String subStr = longStr.substring(1,10); substrings.add(subStr); } } }
下面的代碼出了甚麼成績呢?當它在JDK 7u6之前的版本上運轉的時刻,前往的字符串將會保留一個對誰人1M閣下年夜小的字符串的援用,假如你運轉的時刻設置為-Xmx100m,你會獲得一個意想不到的oom毛病。聯合你試驗情況中平台和版本的差別,傷腦經的工作就發生了。
如今假如你想掩飾你的萍蹤,我們可以引進一些加倍高等的概念。好比
我願望我們給了你一些思慮的原資料和當你想補綴或人時的一些素材。這將帶來無限無盡的調試。除非你的同伙應用 Plumbr來查找溢出的地點地。