OutOfMemoryError内存不足和StackOverflowError堆栈溢出示例详解

 更新时间:2023年09月01日 14:28:06   作者:小名源治  
这篇文章主要为大家介绍了OutOfMemoryError内存不足和StackOverflowError堆栈溢出示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

OutOfMemoryError(内存不足)

如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出
OutOfMemoryError异常。

StackOverflowError(堆栈溢出)

如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。

测试一:单线程中通过两个方法不断相互调用

单线程中,通过两个方法不断的相互调用,栈的深度到达了虚拟机的最大深度。

结果:抛出StackOverflowError异常,

public class JVMStackOverflow {
    static void  dfs(){
        a();
    }
    private static void a() {
        dfs();
    }
    public static void main(String[] args) throws Throwable {
        dfs();
    }
}

测试二:使用单线程,定义了大量的本地变量

使用单线程,定义了大量的本地变量,增大此方法帧中本地变量表的长度。

结果:抛出StackOverflowError异常,异常出现时输出的堆栈深度相应缩小。

public class JavaVMStackSOF {
    private static int stackLength = 0;
    public static void test() {
        long unused1, unused2, unused3, unused4, unused5,
                unused6, unused7, unused8, unused9, unused10,
                unused11, unused12, unused13, unused14, unused15,
                unused16, unused17, unused18, unused19, unused20,
                unused21, unused22, unused23, unused24, unused25,
                unused26, unused27, unused28, unused29, unused30,
                unused31, unused32, unused33, unused34, unused35,
                unused36, unused37, unused38, unused39, unused40,
                unused41, unused42, unused43, unused44, unused45,
                unused46, unused47, unused48, unused49, unused50,
                unused51, unused52, unused53, unused54, unused55,
                unused56, unused57, unused58, unused59, unused60,
                unused61, unused62, unused63, unused64, unused65,
                unused66, unused67, unused68, unused69, unused70,
                unused71, unused72, unused73, unused74, unused75,
                unused76, unused77, unused78, unused79, unused80,
                unused81, unused82, unused83, unused84, unused85,
                unused86, unused87, unused88, unused89, unused90,
                unused91, unused92, unused93, unused94, unused95,
                unused96, unused97, unused98, unused99, unused100;
        stackLength ++;
        test();
        unused1 = unused2 = unused3 = unused4 = unused5 =
                unused6 = unused7 = unused8 = unused9 = unused10 =
                        unused11 = unused12 = unused13 = unused14 = unused15 =
                                unused16 = unused17 = unused18 = unused19 = unused20 =
                                        unused21 = unused22 = unused23 = unused24 = unused25 =
                                                unused26 = unused27 = unused28 = unused29 = unused30 =
                                                        unused31 = unused32 = unused33 = unused34 = unused35 =
                                                                unused36 = unused37 = unused38 = unused39 = unused40 =
                                                                        unused41 = unused42 = unused43 = unused44 = unused45 =
                                                                                unused46 = unused47 = unused48 = unused49 = unused50 =
                                                                                        unused51 = unused52 = unused53 = unused54 = unused55 =
                                                                                                unused56 = unused57 = unused58 = unused59 = unused60 =
                                                                                                        unused61 = unused62 = unused63 = unused64 = unused65 =
                                                                                                                unused66 = unused67 = unused68 = unused69 = unused70 =
                                                                                                                        unused71 = unused72 = unused73 = unused74 = unused75 =
                                                                                                                                unused76 = unused77 = unused78 = unused79 = unused80 =
                                                                                                                                        unused81 = unused82 = unused83 = unused84 = unused85 =
                                                                                                                                                unused86 = unused87 = unused88 = unused89 = unused90 =
                                                                                                                                                        unused91 = unused92 = unused93 = unused94 = unused95 =
                                                                                                                                                                unused96 = unused97 = unused98 = unused99 = unused100 = 0;
    }
    public static void main(String[] args) {
        try {
            test();
        }catch (Error e){
            System.out.println("stack length:" + stackLength);
            throw e;
        }
    }
}

可见无论是由于栈帧太大还是虚拟机栈容量太小,当新的栈帧内存无法分配的时候,HotSpot虚拟机抛出的都是StackOverflowError异常。可是如果在允许动态扩展栈容量大小的虚拟机上,相同代码则会导致不一样的情况。譬如远古时代的Classic虚拟机,这款虚拟机可以支持动态扩展栈内存的容量,它运行方法二就会产生OutOfMemoryError异常。

测试三:什么情况下可以产生OutOfMemoryError异常呢?

通过不断建立线程的方式,在HotSpot上也是可以产生内存溢出异常的。但是这样产生的内存溢出异常和栈空间是否足够并不存在任何直接的关系,主要取决于操作系统本身的内存使用状态。甚至可以说,在这种情况下,给每个线程的栈分配的内存越大,反而越容易产生内存溢出异常。

public class JVMStackOOM {
    private void dontStop() {
        while (true) {
        }
    }
    public void stackLeakByThread() {
        while (true) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    dontStop();
                }
            });
            thread.start();
        }
    }
    public static void main(String[] args) throws Throwable {
        JVMStackOOM oom = new JVMStackOOM();
        oom.stackLeakByThread();
    }
}

以上就是OutOfMemoryError内存不足和StackOverflowError堆栈溢出示例详解的详细内容,更多关于OutOfMemoryError StackOverflowError的资料请关注脚本之家其它相关文章!

相关文章

  • SpringMVC拦截器快速掌握下篇

    SpringMVC拦截器快速掌握下篇

    拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行。本文将详细讲讲SpringMVC中拦截器的概念及入门案例,感兴趣的可以尝试一下
    2022-08-08
  • Spring Boot 初始化运行特定方法解析

    Spring Boot 初始化运行特定方法解析

    这篇文章主要介绍了Spring Boot 初始化运行特定方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • JAVA中字符串如何与整型数字相加

    JAVA中字符串如何与整型数字相加

    这篇文章主要介绍了JAVA中字符串如何与整型数字相加,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • Java基础教程之对象的方法与数据成员

    Java基础教程之对象的方法与数据成员

    这篇文章主要介绍了Java基础教程之对象的方法与数据成员,本文讲解对象的方法与数据成员相关知识,因为java是面向对象语言,本文的知识都是经常要用到的,需要的朋友可以参考下
    2014-08-08
  • @RequestBody注解Ajax post json List集合数据请求400/415的处理

    @RequestBody注解Ajax post json List集合数据请求400/41

    这篇文章主要介绍了@RequestBody注解Ajax post json List集合数据请求400/415的处理方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • Java中static的特点

    Java中static的特点

    本文主要介绍了Java中static的特点。具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • Java synchronized关键字性能考量及优化探索

    Java synchronized关键字性能考量及优化探索

    这篇文章主要为大家介绍了Java synchronized关键字性能考量及优化探索示例分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • java根据扩展名获取系统图标和文件图标示例

    java根据扩展名获取系统图标和文件图标示例

    这篇文章主要介绍了java根据扩展名获取系统图标和文件图标示例,需要的朋友可以参考下
    2014-03-03
  • Java开发中为什么要使用单例模式详解

    Java开发中为什么要使用单例模式详解

    单例对于大家来说并不陌生,但是在什么时候用单例呢?为什么要用呢?本文就带大家了解一下为什么要使用单例,文中有非常详细的介绍,需要的朋友可以参考下
    2021-06-06
  • SpringBoot在自定义类中调用service层mapper层方式

    SpringBoot在自定义类中调用service层mapper层方式

    这篇文章主要介绍了SpringBoot在自定义类中调用service层mapper层方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03

最新评论