<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    10分鐘搞懂各種內(nèi)存溢出案例??!

    共 14122字,需瀏覽 29分鐘

     ·

    2021-05-29 21:06

    作為程序員,多多少少都會遇到一些內(nèi)存溢出的場景,如果你還沒遇到,說明你工作的年限可能比較短,或者你根本就是個假程序員!哈哈,開個玩笑。今天,我們就以Java代碼的方式來列舉幾個典型的內(nèi)存溢出案例,希望大家在日常工作中,盡量避免寫這些low水平的代碼。小伙伴們點贊,在看,留言,走起呀

    我們先來看看今天要介紹哪些內(nèi)存溢出案例,冰河這里總結(jié)了一張圖,如下所示。

    說干就干,咱們開始吧??!

    定義主類結(jié)構(gòu)

    首先,我們創(chuàng)建一個名稱為BlowUpJVM的類,之后所有的案例實驗都是基于這個類進行。如下所示。

    public class BlowUpJVM {  

    棧深度溢出

    public static void  testStackOverFlow()
          BlowUpJVM.testStackOverFlow(); 

    棧不斷遞歸,而且沒有處理,所以虛擬機棧就不斷深入不斷深入,棧深度就這樣溢出了。

    永久代內(nèi)存溢出

    public static void testPergemOutOfMemory1()
       //方法一失敗 
       List<String> list = new ArrayList<String>(); 
       while(true){ 
          list.add(UUID.randomUUID().toString().intern()); 
       } 

    打算把String常量池堆滿,沒想到失敗了,JDK1.7后常量池放到了堆里,也能進行垃圾回收了。

    然后換種方式,使用cglib,用Class把老年代取堆滿

    public static void testPergemOutOfMemory2()
       try { 
          while (true) { 
             Enhancer enhancer = new Enhancer(); 
             enhancer.setSuperclass(OOM.class)
             enhancer.setUseCache(false); 
             enhancer.setCallback(new MethodInterceptor() { 
                @Override 
                public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable 
                   return proxy.invokeSuper(obj, args); 
                } 
             }); 
             enhancer.create(); 
          } 
       } 
       catch (Exception e){ 
          e.printStackTrace(); 
       } 

    虛擬機成功內(nèi)存溢出了,那JDK動態(tài)代理產(chǎn)生的類能不能溢出呢?

    public static void testPergemOutOfMemory3()
       while(true){ 
       final OOM oom = new OOM(); 
       Proxy.newProxyInstance(oom.getClass().getClassLoader(), oom.getClass().getInterfaces(), new InvocationHandler() { 
             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
                Object result = method.invoke(oom, args); 
                return result; 
             } 
          }); 
       } 

    事實表明,JDK動態(tài)代理差生的類不會造成內(nèi)存溢出,原因是:JDK動態(tài)代理產(chǎn)生的類信息,不會放到永久代中,而是放在堆中。

    本地方法棧溢出

    public static void testNativeMethodOutOfMemory()
       int j = 0
       while(true){ 
          Printer.println(j++); 
          ExecutorService executors = Executors.newFixedThreadPool(50); 
          int i=0
          while(i++<10){ 
             executors.submit(new Runnable() { 
                public void run() 
                } 
             }); 
          } 
       } 

    這個的原理就是不斷創(chuàng)建線程池,而每個線程池都創(chuàng)建10個線程,這些線程池都是在本地方法區(qū)的,久而久之,本地方法區(qū)就溢出了。

    JVM棧內(nèi)存溢出

    public static void testStackOutOfMemory()
        while (true) {   
                Thread thread = new Thread(new Runnable() {   
                       public void run() 
                              while(true){ 
                          } 
                       }   
                });   
                thread.start();   
         }   

    線程的創(chuàng)建會直接在JVM棧中創(chuàng)建,但是本例子中,沒看到內(nèi)存溢出,主機先掛了,不是JVM掛了,真的是主機掛了,無論在mac還是在windows,都掛了。

    溫馨提示,這個真的會死機的。

    堆溢出

    public static void testOutOfHeapMemory()
       List<StringBuffer> list = new ArrayList<StringBuffer>(); 
       while(true){ 
          StringBuffer B = new StringBuffer(); 
          for(int i = 0 ; i < 10000 ; i++){ 
             B.append(i); 
          } 
          list.add(B); 
       } 

    不斷往堆中塞新增的StringBuffer對象,堆滿了就直接溢出了。

    測試案例完整代碼

    public class BlowUpJVM {
        //棧深度溢出
        public static void  testStackOverFlow()
           BlowUpJVM.testStackOverFlow(); 
     } 
        
        //不能引起永久代溢出
        public static void testPergemOutOfMemory1()
           //方法一失敗 
            List<String> list = new ArrayList<String>(); 
           while(true){ 
              list.add(UUID.randomUUID().toString().intern()); 
           } 
        } 
        
        //永久代溢出
        public static void testPergemOutOfMemory2()
           try { 
              while (true) { 
                 Enhancer enhancer = new Enhancer(); 
                 enhancer.setSuperclass(OOM.class)
                 enhancer.setUseCache(false); 
                 enhancer.setCallback(new MethodInterceptor() { 
                    @Override 
                    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable 
                       return proxy.invokeSuper(obj, args); 
                    } 
                 }); 
                 enhancer.create(); 
              } 
           } 
           catch (Exception e){ 
              e.printStackTrace(); 
           } 
        } 
        
        //不會引起永久代溢出
        public static void testPergemOutOfMemory3()
           while(true){ 
           final OOM oom = new OOM(); 
           Proxy.newProxyInstance(oom.getClass().getClassLoader(), oom.getClass().getInterfaces(), new InvocationHandler() { 
                 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
                    Object result = method.invoke(oom, args); 
                    return result; 
                 } 
              }); 
           } 
        } 
        
        //本地方法棧溢出
        public static void testNativeMethodOutOfMemory()
           int j = 0
           while(true){ 
              Printer.println(j++); 
              ExecutorService executors = Executors.newFixedThreadPool(50); 
              int i=0
              while(i++<10){ 
                 executors.submit(new Runnable() { 
                    public void run() 
                    } 
                 }); 
              } 
           } 
        } 
        
        //JVM內(nèi)存溢出
        public static void testStackOutOfMemory()
            while (true) {   
                    Thread thread = new Thread(new Runnable() {   
                           public void run() 
                                  while(true){ 
                              } 
                           }   
                    });   
                    thread.start();   
             }   
        } 
        
        //堆溢出
        public static void testOutOfHeapMemory()
           List<StringBuffer> list = new ArrayList<StringBuffer>(); 
           while(true){ 
              StringBuffer B = new StringBuffer(); 
              for(int i = 0 ; i < 10000 ; i++){ 
                 B.append(i); 
              } 
              list.add(B); 
           } 
        } 

    瀏覽 52
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報
    評論
    圖片
    表情
    推薦
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    黄色一及片自拍 | 成人视频18+在线观看 | Japanese熟女六十路。无限是 | 国产A片精品 | 国产精品亚洲专区在线播放麻豆 |