自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

存儲(chǔ)
今天,我們就以Java代碼的方式來列舉幾個(gè)典型的內(nèi)存溢出案例,希望大家在日常工作中,盡量避免寫這些low水平的代碼。

[[402096]]

大家好,我是冰河~~

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

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

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

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

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

  1. public class BlowUpJVM {   
  2. }  

棧深度溢出

  1. public static void testStackOverFlow(){ 
  2.  
  3. BlowUpJVM.testStackOverFlow(); 
  4.  

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

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

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

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

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

  1. public static void testPergemOutOfMemory2(){  
  2.    try {  
  3.       while (true) {  
  4.          Enhancer enhancer = new Enhancer();  
  5.          enhancer.setSuperclass(OOM.class);  
  6.          enhancer.setUseCache(false);  
  7.          enhancer.setCallback(new MethodInterceptor() {  
  8.             @Override  
  9.             public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
  10.                return proxy.invokeSuper(obj, args);  
  11.             }  
  12.          });  
  13.          enhancer.create();  
  14.       }  
  15.    }  
  16.    catch (Exception e){  
  17.       e.printStackTrace();  
  18.    }  
  19. }  

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

  1. public static void testPergemOutOfMemory3(){  
  2.    while(true){  
  3.    final OOM oom = new OOM();  
  4.    Proxy.newProxyInstance(oom.getClass().getClassLoader(), oom.getClass().getInterfaces(), new InvocationHandler() {  
  5.          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  6.             Object result = method.invoke(oom, args);  
  7.             return result;  
  8.          }  
  9.       });  
  10.    }  
  11. }  

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

本地方法棧溢出

  1. public static void testNativeMethodOutOfMemory(){  
  2.    int j = 0;  
  3.    while(true){  
  4.       Printer.println(j++);  
  5.       ExecutorService executors = Executors.newFixedThreadPool(50);  
  6.       int i=0;  
  7.       while(i++<10){  
  8.          executors.submit(new Runnable() {  
  9.             public void run() {  
  10.             }  
  11.          });  
  12.       }  
  13.    }  
  14. }  

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

JVM棧內(nèi)存溢出

  1. public static void testStackOutOfMemory(){  
  2.     while (true) {    
  3.             Thread thread = new Thread(new Runnable() {    
  4.                    public void run() {  
  5.                           while(true){  
  6.                       }  
  7.                    }    
  8.             });    
  9.             thread.start();    
  10.      }    
  11. }  

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

溫馨提示,這個(gè)真的會(huì)死機(jī)的。

堆溢出

  1. public static void testOutOfHeapMemory(){  
  2.    List<StringBuffer> list = new ArrayList<StringBuffer>();  
  3.    while(true){  
  4.       StringBuffer B = new StringBuffer();  
  5.       for(int i = 0 ; i < 10000 ; i++){  
  6.          B.append(i);  
  7.       }  
  8.       list.add(B);  
  9.    }  
  10. }  

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

測試案例完整代碼

  1. public class BlowUpJVM { 
  2.     //棧深度溢出 
  3.     public static void  testStackOverFlow(){  
  4.        BlowUpJVM.testStackOverFlow();  
  5.  }  
  6.      
  7.     //不能引起永久代溢出 
  8.     public static void testPergemOutOfMemory1(){  
  9.        //方法一失敗  
  10.         List<String> list = new ArrayList<String>();  
  11.        while(true){  
  12.           list.add(UUID.randomUUID().toString().intern());  
  13.        }  
  14.     }  
  15.      
  16.     //永久代溢出 
  17.     public static void testPergemOutOfMemory2(){  
  18.        try {  
  19.           while (true) {  
  20.              Enhancer enhancer = new Enhancer();  
  21.              enhancer.setSuperclass(OOM.class);  
  22.              enhancer.setUseCache(false);  
  23.              enhancer.setCallback(new MethodInterceptor() {  
  24.                 @Override  
  25.                 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
  26.                    return proxy.invokeSuper(obj, args);  
  27.                 }  
  28.              });  
  29.              enhancer.create();  
  30.           }  
  31.        }  
  32.        catch (Exception e){  
  33.           e.printStackTrace();  
  34.        }  
  35.     }  
  36.      
  37.     //不會(huì)引起永久代溢出 
  38.     public static void testPergemOutOfMemory3(){  
  39.        while(true){  
  40.        final OOM oom = new OOM();  
  41.        Proxy.newProxyInstance(oom.getClass().getClassLoader(), oom.getClass().getInterfaces(), new InvocationHandler() {  
  42.              public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  43.                 Object result = method.invoke(oom, args);  
  44.                 return result;  
  45.              }  
  46.           });  
  47.        }  
  48.     }  
  49.      
  50.     //本地方法棧溢出 
  51.     public static void testNativeMethodOutOfMemory(){  
  52.        int j = 0;  
  53.        while(true){  
  54.           Printer.println(j++);  
  55.           ExecutorService executors = Executors.newFixedThreadPool(50);  
  56.           int i=0;  
  57.           while(i++<10){  
  58.              executors.submit(new Runnable() {  
  59.                 public void run() {  
  60.                 }  
  61.              });  
  62.           }  
  63.        }  
  64.     }  
  65.      
  66.     //JVM內(nèi)存溢出 
  67.     public static void testStackOutOfMemory(){  
  68.         while (true) {    
  69.                 Thread thread = new Thread(new Runnable() {    
  70.                        public void run() {  
  71.                               while(true){  
  72.                           }  
  73.                        }    
  74.                 });    
  75.                 thread.start();    
  76.          }    
  77.     }  
  78.      
  79.     //堆溢出 
  80.     public static void testOutOfHeapMemory(){  
  81.        List<StringBuffer> list = new ArrayList<StringBuffer>();  
  82.        while(true){  
  83.           StringBuffer B = new StringBuffer();  
  84.           for(int i = 0 ; i < 10000 ; i++){  
  85.              B.append(i);  
  86.           }  
  87.           list.add(B);  
  88.        }  
  89.     }  
  90. }  

寫在最后

最后,附上并發(fā)編程需要掌握的核心技能知識(shí)圖,祝大家在學(xué)習(xí)并發(fā)編程時(shí),少走彎路。

本文轉(zhuǎn)載自微信公眾號(hào)「冰河技術(shù)」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系冰河技術(shù)公眾號(hào)。

 

責(zé)任編輯:武曉燕 來源: 冰河技術(shù)
相關(guān)推薦

2025-01-21 07:39:04

Linux堆內(nèi)存Golang

2024-12-11 07:00:00

面向?qū)ο?/a>代碼

2025-03-13 06:22:59

2019-08-09 10:33:36

開發(fā)技能代碼

2025-01-20 08:50:00

2021-06-18 07:34:12

Kafka中間件微服務(wù)

2017-03-30 19:28:26

HBase分布式數(shù)據(jù)

2021-07-15 06:43:11

Bash調(diào)試腳本

2024-01-16 07:46:14

FutureTask接口用法

2023-09-18 15:49:40

Ingress云原生Kubernetes

2013-09-13 14:08:01

2023-12-06 08:48:36

Kubernetes組件

2021-04-23 09:50:41

topLinux命令

2014-08-08 09:30:04

android scrollview

2020-10-13 18:22:58

DevOps工具開發(fā)

2024-04-29 07:57:46

分布式流控算法

2019-09-16 09:14:51

2024-01-12 07:38:38

AQS原理JUC

2024-07-05 09:31:37

2023-12-04 18:13:03

GPU編程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)