五种内存溢出案例总结:涵盖栈深度溢出永久代内存溢出本地方法栈溢出JVM栈内存溢出和堆溢出

Posted 冰 河

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了五种内存溢出案例总结:涵盖栈深度溢出永久代内存溢出本地方法栈溢出JVM栈内存溢出和堆溢出相关的知识,希望对你有一定的参考价值。

大家好,我是冰河~~

相信小伙伴们在平时工作的过程中,或多或少都会遇到一个场景:内存溢出。如果你没有遇到过这个场景,那就说明你是个假的程序员。哈哈,开个玩笑,平时工作过程中,我们确实会遇到这个问题。今天,我就将平时工作过程中遇到的内存溢出情况做个简单的总结,以通俗易懂的代码案例的形式直观的分享给大家。希望能够为小伙伴们带来实质性的帮助。

案例介绍

这里,我将在平时工作过程中总结的内存溢出的情况,以代码案例的形式直观的分享给大家,希望能够为小伙伴们带来实质性的帮助。

接下来,我们就以代码案例的形式来分析各种内存溢出的情况。

定义主类结构

首先,我们创建一个类叫做BlowUpJVM,所有的案例实验都是基于这个类进行。

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()); 
    
 

打算把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(); 
    
 

虚拟机成功内存溢出了,那JDK动态代理产生的类能不能溢出呢?

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动态代理差生的类不会造成内存溢出,原因是:JDK动态代理产生的类信息,不会放到永久代中,而是放在堆中。

本地方法栈溢出

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()  
             
         ); 
       
    
 

这个的原理就是不断创建线程池,而每个线程池都创建10个线程,这些线程池都是在本地方法区的,久而久之,本地方法区就溢出了。

JVM栈内存溢出

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

线程的创建会直接在JVM栈中创建,但是本例子中,没看到内存溢出,主机先挂了,不是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对象,堆满了就直接溢出了。

写在最后

如果你想进大厂,想升职加薪,或者对自己现有的工作比较迷茫,都可以私信我交流,希望我的一些经历能够帮助到大家~~

推荐阅读:

好了,今天就到这儿吧,小伙伴们点赞、收藏、评论,一键三连走起呀,我是冰河,我们下期见~~

👇🏻 搜索下方 公众号 关注我👇🏻

以上是关于五种内存溢出案例总结:涵盖栈深度溢出永久代内存溢出本地方法栈溢出JVM栈内存溢出和堆溢出的主要内容,如果未能解决你的问题,请参考以下文章

JVM各种情况内存溢出分析

JVM记一次PermGen space内存溢出实战案例

Java JVM:内存溢出(栈溢出,堆溢出,持久代溢出以及 nable to create native thread)

JVM内存溢出原理及案例分析

Storm程序永久代内存溢出

jvm 内存溢出