qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          關于編寫Java程序讓Jvm崩潰

           今天在書上看到一個作者提出一個問題“怎樣通過編寫Java代碼讓Jvm崩潰”,我看了之后也不懂。帶著問題查了一下,百度知道里面有這樣一個答案:
          1 package jvm;
          2
          3 public class Crash {
          4     public static void main(String[] args) {
          5
          6         //Object[] o = {“abc”};初始值賦值,不會有影響。
          7         Object[] o = null;
          8
          9         while (true) {
          10             o = new Object[] { o };
          11             //輸出的話,jvm就不會崩潰。
          12             //System.out.println(o);
          13         }
          14     }
          15 }
            程序運行十幾秒之后,控制臺會出現這樣的錯誤:
            Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
            at jvm.Crash.main(Crash.java:10)
            很明顯,超出內存空間錯誤。
            我將原程序隨意改了一下,如賦初始值等,對程序無影響。
            可是我將死循環中的o輸出在控制臺的時候,jvm居然一直都不崩,為什么輸出的話,就不會超出內存空間呢?
            我看來,原程序能夠使Jvm崩潰,是因為死循環中,通過舊對象,不斷創建出新的對象,即創造的對象是互相引用的,所以GC是不會回收它們的,造成堆棧溢出。
            仿照這個例子,我寫了一個簡單的類,模仿例子程序中的數組,如下:
          1 package jvm;
          2
          3 public class JvmBean {
          4
          5     JvmBean bean = new JvmBean(this);
          6
          7     public JvmBean(JvmBean bean){
          8         this.bean = bean;
          9     }
          10 }
            然后簡單測試,如下:
          1 package jvm;
          2
          3 public class MyCrash {
          4
          5     public static void main(String[] args) {
          6         JvmBean j = null;
          7         while(true){
          8             j = new JvmBean(j);
          9             //無論輸出不輸出,jvm都會崩潰
          10             //System.out.println(j);
          11         }
          12     }
          13 }
           結果便是控制臺輸出如下的錯誤:
          Exception in thread "main" java.lang.StackOverflowError
          at jvm.JvmBean.<init>(JvmBean.java:5)
          at jvm.JvmBean.<init>(JvmBean.java:5)
          at jvm.JvmBean.<init>(JvmBean.java:5)
          at jvm.JvmBean.<init>(JvmBean.java:5)
          at jvm.JvmBean.<init>(JvmBean.java:5)
            一長串的"at jvm.JvmBean.<init>(JvmBean.java:5)",后面的被我省略了。
            結果看來,同樣也造成了jvm崩潰,可是錯誤類型跟例子程序的不同,說堆棧溢出錯誤,并且無論是否輸出,錯誤都一樣發生,為什么呢?
            由于評論的兩位老兄的熱心指點,兩個問題都水落石出了!
            這里過一下整個流程。
            第一個異常 結合天添老兄說的,Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at jvm.Crash.main(Crash.java:10)是因為程序無法申請到足夠的內存的時候拋出的異常,Object數組o不斷指向新的Object數組,數組元素是原來的Object數組,這使得Object維數越來越高。不斷申請內存空間,最終導致超出jvm中堆的最大值。堆內存溢出。為什么輸出打印,時間會延長呢?yahokuma老兄一言驚醒夢中人!輸出打印的話,虛擬機并不是不會崩潰,而是崩潰的時間大大延長了。而崩潰時間延長其實是假象,是因為輸出屬于IO事件,每次輸出CPU都被中斷,IO很耗時,所以,感覺上才會時間延長。
            第二個異常,yahokuma 老兄在下面評論中已經說的很清楚了,我這里搬過來——“類內部的靜態屬性 > 靜態塊 > 對象屬性 > 構造方法。注意這一點,那就是說 bean屬性會先于JvmBean的構造函數被初始化。在你main函數中,new一個 JvmBean的構造函數之前,類內部的JvmBean對象要優先被初始化,這個類內部的屬性bean的內部同樣也包含了一個JvmBean對象需要被初始化,成循環調用,造 成了棧溢出。”所以異常才會是這個——Exception in thread "main" java.lang.StackOverflowError
            我把原JvmBean改一下
          1 package jvm;
          2
          3 public class JvmBean {
          4
          5     JvmBean bean = null;
          6
          7     public JvmBean(JvmBean bean){
          8         this.bean = bean;
          9     }
          10 }
            這樣最終得到的結果跟第一個例子一樣了。
            如何使Jvm崩潰呢?如果想使它堆內存空間不足,造成典型的內存泄漏,可以創建對象,使它們不斷向深層次引用。產生Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 這樣的錯誤。如果想使他們棧空間不足,最簡單的,就是在方法里,如構造方法里不斷申請新的內存空間就夠了,如我第二個錯誤例子的示范。

          posted on 2014-04-29 11:06 順其自然EVO 閱讀(786) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2014年4月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 中宁县| 虞城县| 巨野县| 福鼎市| 分宜县| 临潭县| 金山区| 久治县| 西青区| 洪泽县| 台前县| 揭东县| 安达市| 邹城市| 安岳县| 仲巴县| 张家界市| 兰州市| 邢台县| 江孜县| 封开县| 临武县| 绥芬河市| 宁河县| 小金县| 全南县| 岱山县| 苗栗市| 岗巴县| 广灵县| 甘肃省| 四平市| 岳池县| 余江县| 桂平市| 门源| 馆陶县| 清水河县| 江门市| 峨眉山市| 昭苏县|