以Java代码的方式总结几个典型的内存溢出案例

一、图示

我们先来看看今天要介绍哪些内存溢出案例,这里总结了一张图,如下所示。

二、定义主类结构

首先,我们创建一个名称为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对象,堆满了就直接溢出了。

八、测试案例完整代码

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内存溢出
    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);
       }
    }
}

到此这篇关于以Java代码的方式列举几个典型的内存溢出案例总结的文章就介绍到这了,更多相关Java内存溢出内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 完美解决java读取大文件内存溢出的问题

    1. 传统方式:在内存中读取文件内容 读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速读取文件行的方法: Files.readLines(new File(path), Charsets.UTF_8); FileUtils.readLines(new File(path)); 实际上是使用BufferedReader或者其子类LineNumberReader来读取的. 传统方式的问题: 是文件的所有行都被存放在内存中,当文件足够大时很快就会

  • Java内存溢出和内存泄露

    虽然jvm可以通过GC自动回收无用的内存,但是代码不好的话仍然存在内存溢出的风险. 一.为什么要了解内存泄露和内存溢出? 1.内存泄露一般是代码设计存在缺陷导致的,通过了解内存泄露的场景,可以避免不必要的内存溢出和提高自己的代码编写水平: 2.通过了解内存溢出的几种常见情况,可以在出现内存溢出的时候快速的定位问题的位置,缩短解决故障的时间.  二.基本概念  理解这两个概念非常重要. 内存泄露:指程序中动态分配内存给一些临时对象,但是对象不会被GC所回收,它始终占用内存.即被分配的对象可达但已无

  • Java内存溢出案例模拟和原理分析过程

    在JVM虚拟机规范中,Java虚拟机运行时数据区域除了程序计数器(Program Counter Register)外都有可能出现OutOfMemoryError的情况,使用Hotspot虚拟机简单的模拟堆栈内存溢出的场景,方便快速定位是什么区域的内存溢出. 堆 通过VM参数设置Java堆的大小,避免堆可扩展内存(设定-Xms和Xmx一样可避免堆自动扩展): 通过设定-XX:+HeapDumpOnOutOf-MemoryError可以让虚拟机在出现内存溢出异常的时候Dump出当前的内存堆转储快照

  • Java 常见的几种内存溢出异常的原因及解决

    内存溢出的异常有很多,并且每种内存溢出都会有不同的异常信息和解决方式,下面会列出常见的几种内存溢出异常 堆内存溢出 java.lang.OutOfMemoryError: Java heap space 原因: 当堆内存不足,并且已经达到JVM设置的最大值,无法继续申请新的内存,存活的对象在堆内存中无法被回收,那么就会抛出该异常,表示堆内存溢出. 当一次从数据库查询大量数据,堆内存没有足够的内存可以存放大量的数据 大量的强引用对象在堆内存中存活,GC无法回收这些对象,新创建的对象在新生代无法进行

  • Java 堆内存溢出原因分析

    前言 任何使用过基于 Java 的企业级后端应用的软件开发者都会遇到过这种低劣.奇怪的报错,这些报错来自于用户或是测试工程师: java.lang.OutOfMemoryError:Java heap space. 为了弄清楚问题,我们必须返回到算法复杂性的计算机科学基础,尤其是"空间"复杂性.如果我们回忆,每一个应用都有一个最坏情况特征.具体来说,在存储维度方面,超过推荐的存储将会被分配到应用程序上,这是不可预测但尖锐的问题.这导致了堆内存的过度使用,因此出现了"内存不够&

  • 解决Java导入excel大量数据出现内存溢出的问题

    问题:系统要求导入40万条excel数据,采用poi方式,服务器出现内存溢出情况. 解决方法:由于HSSFWorkbook workbook = new HSSFWorkbook(path)一次性将excel load到内存中导致内存不够. 故采用读取csv格式.由于csv的数据以x1,x2,x3形成,类似读取txt文档. private BufferedReader bReader; /** * 执行文件入口 */ public void execute() { try { if(!path.

  • java内存泄漏与内存溢出关系解析

    这篇文章主要介绍了java内存泄漏与内存溢出关系解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory: 内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光. memory leak会最终会导致out of memory!

  • 详解Java内存溢出的几种情况

    JVM(Java虚拟机)是一个抽象的计算模型.就如同一台真实的机器,它有自己的指令集和执行引擎,可以在运行时操控内存区域.目的是为构建在其上运行的应用程序提供一个运行环境.JVM可以解读指令代码并与底层进行交互:包括操作系统平台和执行指令并管理资源的硬件体系结构. 1. 前言 JVM提供的内存管理机制和自动垃圾回收极大的解放了用户对于内存的管理,大部分情况下不会出现内存泄漏和内存溢出问题.但是基本不会出现并不等于不会出现,所以掌握Java内存模型原理和学会分析出现的内存溢出或内存泄漏,对于使用J

  • Java内存溢出实现原因及解决方案

    1.JVM Heap(堆)溢出:java.lang.OutOfMemoryError: Java heap space JVM在启动的时候会自动设置JVM Heap的值, 可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置.Heap的大小是Young Generation 和Tenured Generaion 之和.在JVM中如果98%的时间是用于GC,且可用的Heap size 不足2%的时候将抛出此异常信息. 解决方法:手动设置JVM Heap(堆)的大小. Java堆用于储存

  • JAVA内存溢出解决方案图解

    这篇文章主要介绍了JAVA内存溢出解决方案图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.在apache-tomcat-7.0.70\bin\catalina.bat(Linux 系统则在catalina.sh) 文件下的 echo Using CATALINA_BASE: "%CATALINA_BASE%" 上面插入以下代码 set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=256

  • Java编程常见内存溢出异常与代码示例

    Java 堆是用来存储对象实例的, 因此如果我们不断地创建对象, 并且保证 GC Root 和创建的对象之间有可达路径以免对象被垃圾回收, 那么当创建的对象过多时, 会导致 heap 内存不足, 进而引发 OutOfMemoryError 异常. /** * @author xiongyongshun * VM Args: java -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError */ public class OutOfMemoryErrorTe

随机推荐