写代码实现堆溢出、栈溢出、永久代溢出、直接内存溢出

Heap overflow堆溢出(一) 堆溢出介绍: 堆溢出是指程序向某个堆块中写入的字节数超过了堆块本身可使用的字节数(之所以是可使用而不是用户申请的字节数,是因为堆管理器会对用户所申请的字节数进行调整,这也导致可利用的字节数都不小于用户申请的字节数),因而导致了数据溢出,并覆盖到物理相邻的高地址...... 阅读详情

常见溢出

栈溢出(StackOverflowError)
堆溢出(OutOfMemoryError:Java heap space)
永久代溢出(OutOfMemoryError: PermGen space)
直接内存溢出

一、堆溢出

创建对象时如果没有可以分配的堆内存,JVM就会抛出OutOfMemoryError:java heap space异常。堆溢出实例:


/**
 * 堆溢出
 * 
 * VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 */
public class Heap {
	
	public static void main(String[] args) {
		List<byte[]> list = new ArrayList<>();
		int i = 0;
		while (true) {
			list.add(new byte[5 * 1024 * 1024]);
			System.out.println("分配次数:" + (++i));
		}
	}
 
}

运行结果:
分配次数:1
分配次数:2
分配次数:3

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid2464.hprof ...
Heap dump file created [16991068 bytes in 0.047 secs]

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.ghs.test.OOMTest.main(OOMTest.java:16)

二、栈溢出

栈空间不足时,需要分下面两种情况处理:

线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError
虚拟机在扩展栈深度时无法申请到足够的内存空间,将抛出OutOfMemberError
附:当前大部分的虚拟机栈都是可动态扩展的。

1、栈空间不足——StackOverflowError实例

/**
 * 栈溢出
 */
public class Stack {
 
	public static void main(String[] args) {
		new Stack().test();
	}
 
	public void test() {
		test();
	}
 
}

2、栈空间不足——OutOfMemberError实例

单线程情况下,不论是栈帧太大还是虚拟机栈容量太小,都会抛出StackOverflowError,导致单线程情境下模拟栈内存溢出不是很容易,不过通过不断的建立线程倒是可以产生内存溢出异常。

public class StackSOFTest {
 
    int depth = 0;
 
    public void sofMethod(){
        depth ++ ;
        sofMethod();
    }
 
    public static void main(String[] args) {
        StackSOFTest test = null;
        try {
            test = new StackSOFTest();
            test.sofMethod();
        } finally {
            System.out.println("递归次数:"+test.depth);
        }
    }
}


执行结果:
递归次数:982
Exception in thread "main" java.lang.StackOverflowError
    at com.ghs.test.StackSOFTest.sofMethod(StackSOFTest.java:8)
    at com.ghs.test.StackSOFTest.sofMethod(StackSOFTest.java:9)
    at com.ghs.test.StackSOFTest.sofMethod(StackSOFTest.java:9)
……后续堆栈信息省略
执行结果:
递归次数:982
Exception in thread "main" java.lang.StackOverflowError
    at com.ghs.test.StackSOFTest.sofMethod(StackSOFTest.java:8)
    at com.ghs.test.StackSOFTest.sofMethod(StackSOFTest.java:9)
    at com.ghs.test.StackSOFTest.sofMethod(StackSOFTest.java:9)
……后续堆栈信息省略

三、永久代溢出

永久代溢出可以分为两种情况,第一种是常量池溢出,第二种是方法区溢出。

1、永久代溢出——常量池溢出

要模拟常量池溢出,可以使用String对象的intern()方法。如果常量池包含一个此String对象的字符串,就返回代表这个字符串的String对象,否则将String对象包含的字符串添加到常量池中。

public class ConstantPoolOOMTest {
 
    /**
     * VM Args:-XX:PermSize=10m -XX:MaxPermSize=10m
     * @param args
     */
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        int i=1;
        try {
            while(true){
                list.add(UUID.randomUUID().toString().intern());
                i++;
            }
        } finally {
            System.out.println("运行次数:"+i);
        }
    }
}

运行结果:
……比较尴尬的是,通过intern,始终无法模拟出常量池溢出,我的猜想是JDK7对常量池做了优化。
如果哪位大神成功模拟出来了,还望指点一二。

因为在JDK1.7中,当常量池中没有该字符串时,JDK7的intern()方法的实现不再是在常量池中创建与此String内容相同的字符串,而改为在常量池中记录Java Heap中首次出现的该字符串的引用,并返回该引用。
简单来说,就是对象实际存储在堆上面,所以,让上面的代码一直执行下去,最终会产生堆内存溢出。
下面我将堆内存设置为:-Xms5m -Xmx5m,执行上面的代码,运行结果如下:

运行次数:58162
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.lang.Long.toUnsignedString(Unknown Source)
    at java.lang.Long.toHexString(Unknown Source)
    at java.util.UUID.digits(Unknown Source)
 
    at java.util.UUID.toString(Unknown Source)
    at com.ghs.test.ConstantPoolOOMTest.main(ConstantPoolOOMTest.java:18)

2、永久代溢出——方法区溢出

方法区存放Class的相关信息,下面借助CGLib直接操作字节码,生成大量的动态类。

public class MethodAreaOOMTest {
 
    public static void main(String[] args) {
        int i=0;
        try {
            while(true){
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(OOMObject.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();
                i++;
            }
        } finally{
            System.out.println("运行次数:"+i);
        }
    }
 
    static class OOMObject{
 
    }
}


 
运行结果:
 
运行次数:56
Exception in thread "main" 
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"

四、直接内存溢出

DirectMemory可以通过-XX:MaxDirectMemorySize指定,如果不指定,默认与Java堆的最大值(-Xmx指定)一样。
NIO会使用到直接内存,你可以通过NIO来模拟,在下面的例子中,跳过NIO,直接使用UnSafe来分配直接内存。

public class DirectMemoryOOMTest {

    /**
     * VM Args:-Xms20m -Xmx20m -XX:MaxDirectMemorySize=10m
     * @param args
     */
    public static void main(String[] args) {
        int i=0;
        try {
            Field field = Unsafe.class.getDeclaredFields()[0];
            field.setAccessible(true);
            Unsafe unsafe = (Unsafe) field.get(null);
            while(true){
                unsafe.allocateMemory(1024*1024);
                i++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            System.out.println("分配次数:"+i);
        }
    }
}

运行结果:
Exception in thread "main" java.lang.OutOfMemoryError
    at sun.misc.Unsafe.allocateMemory(Native Method)
    at com.ghs.test.DirectMemoryOOMTest.main(DirectMemoryOOMTest.java:20)
分配次数:27953

总结:
栈内存溢出:程序所要求的栈深度过大。
堆内存溢出:分清内存泄露还是 内存容量不足。泄露则看对象如何被 GC Root 引用,不足则通过调大-Xms,-Xmx参数。
永久代溢出:Class对象未被释放,Class对象占用信息过多,有过多的Class对象。
直接内存溢出:系统哪些地方会使用直接内存。

原文出处

https://blog.youkuaiyun.com/u011983531/article/details/63250882

在这里插入图片描述

区分堆溢出和栈溢出的方法 在 C 语言中,区分堆溢出(Heap Overflow)和栈溢出(Stack Overflow)通常依赖于理解它们的特性和行为。 阅读详情

相关推荐

Java 各种溢出测试

Java 各种溢出测试 前置知识点:Java内存组成 注意上图:蓝色为所有线程共享的数据区,紫色为线程的私有区。 1)程序计数器: 在计算机组成结构这门课里面,我们就学到CPU里面有个PC寄存器,这个寄存器主要指CPU当前运行的指令。 在这里,其实也是一样的,对于每一个线程,都有一个PCR,用来记录程序在当前线程执行的位置。当线程阻塞后然后再重新运行,就可以在PC记录的位...

github_38838414的博客 1511

【pwn学习】堆溢出(一)

pwn中堆溢出的学习

Morphy_Amo的博客 6496

什么是内存溢出(Out Of Memory---OOM)和内存泄露 (Memory Leak)

1、内存溢出:(Out Of Memory---OOM) 系统已经不能再分配出你所需要的空间,比如系统现在只有1G的空间,但是你偏偏要2个G空间,这就叫内存溢出 例子:一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出。 比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出。说白了就是我承受不了那么多,那就报错。 2、内存泄漏: (Memory Leak) 强引用所指向的对...

小小鱼儿小小林的博客 1万+

写代码实现栈溢出、堆溢出、永久代溢出、直接内存溢出

栈溢出(StackOverflowError) 堆溢出(OutOfMemoryError:Java heap space) 永久代溢出(OutOfMemoryError: PermGen space) 直接内存溢出 一、堆溢出 创建对象时如果没有可以分配的堆内存,JVM就会抛出OutOfMemoryError:java heap space异常。堆溢出实例: /** * 堆溢出 *...

yamaxifeng_132的专栏 1978

贝莱德(BlackRock)—— 阿拉丁(Aladdin)平台的 AI 赋能升级

全称(资产、负债、债务与衍生品投资网络),是贝莱德自主研发的一体化投资管理与风险管理技术平台,被誉为全球资管行业的 “

xm_mm的博客 1720

苹果开发者账号( Apple Developer)登录出现:你的 Apple ID 暂时不符合使用此应用程序的条件(您的apple账户不符合资格)

Apple开发对于新手来说确实可能会遇到各种问题,在遇到 Apple Developer 账号登录问题时,除了检查账号的安全性设置和协议确认外,还需要考虑账号的具体配置问题,比如主邮箱的设置。

Winter_Sun灬的博客 4116

【JVM】Java内存溢出分析(堆溢出、栈溢出、方法区溢出、直接内存溢出)

Java内存溢出的原因为程序在申请内存(堆/栈/方法区/直接内存等等)时,没有足够的内存空间。

小明的Java问道之路 5232

Leaflet 加载天地图完整配置指南:从插件修改到无限缩放(附源码)

本文详细介绍了Leaflet与天地图深度集成的完整配置指南,包括插件修改、无限缩放实现及源码示例。通过解析天地图服务的WMTS协议、双投影支持和密钥机制,帮助开发者突破缩放级别限制,优化地图应用性能,适用于Web地图开发和高精度GIS系统。

weixin_27180827的博客 440

堆溢出、栈溢出、永久代溢出、直接内存溢出,无法创建本地线程的分析以及代码实现

堆溢出、栈溢出、永久代溢出、直接内存溢出,无法创建本地线程的分析以及代码实现_T-OPEN的博客-优快云博客

m0_37777700的博客 2191

生成式引擎优化(GEO):启动GEO优化的5个有效策略

随着生成式AI的普及,传统SEO正被GEO(生成式引擎优化)取代。本文提出GEO五大核心策略:用户意图解析、结构化内容设计、语义关键词优化、对话式内容创作和权威信源建设。研究表明,优化后的内容在AI答案中的引用率提升300%,点击率增长27%。文章还介绍了BERT模型、Schema标记等关键技术工具,并指出未来GEO将向多模态优化、实时数据更新方向发展。企业需避免简单堆砌关键词,应建立长期内容策略,通过结构化、权威性内容在AI时代保持竞争优势。

解锁AI流量新红利!🚀 GEO优化(生成引擎优化)助您掌控AI搜索,让AI成为您的品牌最佳代言人! 2785

深入解析TMC2209 UART寄存器配置:从基础指令到高级参数调优

本文深入解析TMC2209 UART寄存器配置,从基础指令到高级参数调优,涵盖电流控制、微步细分等关键设置。通过实战案例和优化技巧,帮助开发者高效配置步进电机驱动,提升系统性能和稳定性。特别介绍了UART通信协议和CRC校验实现,确保数据传输可靠性。

tequila的博客 1159

代码实现堆溢出、栈溢出、永久代溢出、直接内存溢出

栈溢出(StackOverflowError) 堆溢出(OutOfMemoryError:Java heap space) 永久代溢出(OutOfMemoryError: PermGen space) 直接内存溢出 一、堆溢出 创建对象时如果没有可以分配的堆内存,JVM就会抛出OutOfMemoryError:java heap space异常。 堆溢出实例: /** * VM A...

Null的博客 2282

RISC-V CPU设计(三)---多周期CPU的设计与实现

基本情况 本多周期CPU支持RV32I指令集(fence,ecall,ebreak除外),已通过部分指令的测试,如代码有bug,欢迎指出。 模块划分 代码将CPU划分为以下几个模块: 1.控制单元:ControlUnit 用于产生控制信号,是CPU的大脑,指挥中枢。 2.分支决策单元:BranchUnit 用于决定B型指令是否发生跳转 3.立即数单元:ImmUnit 用于从指令中解析出立即数. 4.寄存器堆:RegisterFile RISC-V的32个寄存器,其中x0寄存器恒为0,不可更改。 5.指令存储

qq_40268672的博客 5540

java栈溢出堆溢出_栈溢出,堆溢出,永久代溢出,内存泄漏排查

栈溢出,堆溢出,永久代溢出,内存泄漏排查JAVA虚拟机1.虚拟机栈和本地方法栈溢出:1.如果线程请求的栈深度大于虚拟机所允许的最大深度,抛出StackOverflowError异常。单线程下,递归太深或方法调用层级过多,使栈帧太大或虚拟机栈容量太小,都会抛出SOF异常。2.如果虚拟机栈在扩展栈时无法申请到足够的内存空间,抛出OutofMemoryError异常。多线程下,不断建立线程,可使内存溢出...

weixin_39683144的博客 401

36、R语言中的回归模型与机器学习算法

本文介绍了R语言中多种回归模型和机器学习算法,包括Cox回归模型、数据平滑方法(如样条函数、多项式曲面拟合和核平滑)以及回归树模型等。重点讲解了这些方法的实现函数、参数说明以及实际应用示例,如使用`coxph`进行生存分析、使用`spline`和`smooth.spline`进行数据平滑处理、使用`loess`和`locpoly`进行非参数回归分析,以及使用`rpart`构建和可视化回归树。此外,还涉及了模型评估与优化策略,如数据拆分、交叉验证和树的修剪。通过这些方法,可以更好地处理复杂数据集并提升模型性能

yhn456789的博客 122

40、基于指令的GPU编程:OpenACC与OpenMP的深入解析

本文深入解析了两种基于指令的GPU编程模型——OpenACC和OpenMP。从编程复杂度、数据处理方式和性能表现等多个方面对两者进行了对比分析,并结合实际应用场景提供了选择建议。通过详细的代码示例和性能测试结果,帮助开发者更好地理解和应用这两种编程模型,以充分发挥GPU的并行计算能力。

q5r6s7的博客 134

JVM各种情况内存溢出分析

目录 1 直接内存溢出 2 内存溢出 2.1 堆溢出 2.2.1 堆溢出案例 2.3 永久代或元空间溢出 2.3.1 永久代或元空间溢出案例 2.4 栈溢出 2.4.1 栈溢出案例 2.5 非常规溢出 1 直接内存溢出 直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是 JVM 规范中定义的内存区域。但这部分内存也被频繁的使用,而且也可能导致 OutOfMemoryError 异常出现。...

赵广陆 6511

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

学习笔记 --- JVM 堆溢出、栈溢出、永久代溢出、直接内存溢出

栈溢出(StackOverflowError)           ---    递归引起  栈空间不足      ---   线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError 堆溢出(OutOfMemoryError:Java heap space)            ---  死循环,或者内存不够,创建对象时如果没有可以分配的堆内存     ...

tianyeshiye 509

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Java中堆溢出和栈溢出

Java虚拟机所管理的内存将会包括以下几个运行时数据区域。

qq_55754838的博客 967

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

分析Java堆:内存溢出的原因

1、堆溢出   一般来说,绝大部分Java的内存溢出都属于堆溢出。原因是因为大量对象占据了堆空间,这些对象都持有强引用导致无法回收,当对象大小之和大于Xmx参数指定的堆空间时就会发生堆溢出; 解决办法 使用Xmx参数指定一个更大的堆空间; 由于堆空间不可能无限增长,分析找到大量占用对空间的对象,在应用程序上做出优化; 2、直接内存溢出 在Java的NIO中,支持直接内存的使用,通过Java代码获得一块堆外的内存空间。直接内存的申请速度一般比堆内存慢,但是访问速度快于堆内存。 对于那些可复用的,并且会被经

Yisnow.的博客 7279
上一篇: 常见OOM现象
下一篇: MySQL之MVVC简介
牧竹子
博客等级 码龄17年 572粉丝 233原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值