通过代码实现 OutOfMemory

Intro

来尝试写一个发生 OutOfMemoryException 的代码吧,开启煞笔代码第三篇 —— OutofMemory

OutOfMemory

OutOfMemory 顾名思义就是内存不足,在 .NET 中当内存不足的时候就会抛出 OutOfMemoryException 的异常。

想要触发 OutOfMemoryException 就要满足内存不足的条件,在 .NET Framework 中可能就只能一直分配内存直到内存不足,再没有足够的内存可以分配了,在 .NET Core 3.x 版本以后,微软引入了一些 GC 的配置,我们可以通过这些配置来指定最大的 GC 内存,这样我们就可以实现触发 OutOfMemoryException 而不影响其他应用程序正常运行的目标了。在 .NET 5 中我们又可以更进一步更精细的控制 GC 使用的内存了,在 .NET 5 中我们可以针对每个堆(SOH/LOH/POH)来设置内存限制。

GC 堆内存限制配置

我们测试的示例使用限制 GC 堆大小 (Heap Limit) 的方式来限制应用程序的内存占用以免影响到别的应用程序正常运行(该配置只针对 64 位电脑有效,现在的电脑应该大多都是64位吧)。

配置的方式有两种,一种是通过环境变量来配置,一种是通过 runtime.config.json 来配置

通过环境变量配置 COMPlus_GCHeapHardLimit 为要配置的内存大小,需要注意的是通过环境变量配置的时候指定的值需要是十六进制的值,通过 runtimeconfig.json 配置的时候是直接用十进制的数值

因为我们只是想简单的测试一下,不能影响别的应用程序,而且不能在代码里配置当前进程的环境变量,因为进程启动的时候 GC 的配置就已经加载好了,在代码里配置当前进程的环境变量来改变 GC 配置是不会生效的,所以我们选择配置 runtimeconfig.json 来测试,在项目的 bin 目录下可以找到 runtimeconfig.json 文件,我们修改这一个文件即可(使用 runtimeconfig.json 的时候需要注意先生成一下,然后再更新 runtimeconfig.json 文件)

测试配置如下:

{
"runtimeOptions": {
"tfm": "netcoreapp3.1",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "3.1.0"
},
"configProperties": {
"System.GC.HeapHardLimit": 1048576
}
}
}

测试代码

测试代码如下:

Console.ReadLine();
var bytes = GC.GetTotalAllocatedBytes();
Console.WriteLine($"AllocatedBytes: { bytes } bytes");
var list = new List<byte[]>();
try
{
while (true)
{
list.Add(new byte[85000]);
}
}
catch (OutOfMemoryException)
{
Console.WriteLine(nameof(OutOfMemoryException));
Console.WriteLine(list.Count);
bytes = GC.GetTotalAllocatedBytes();
Console.WriteLine($"AllocatedBytes: { bytes } bytes");
}
Console.ReadLine();

测试输出如下:

上面的测试代码使用的 byte 数组的长度是 85000 的原因是,当要分配的对象大于等于 85k(85000)时会直接分配到大对象堆中,正好可以测试一下。

我们使用微软的 dotnet dump 诊断工具来测试一下

第一次 dump 是在 list 对象创建之前进行的,第二次 dump 是发生 OutOfMemory 之后的

从上面的 dump 结果可以看的出来,byte 数组的对象确实是分配在大对象堆(LOH)上的,几乎所有的内存分配都在大对象堆中,有一些小对象从0 代升到了 1代。

More

上面的测试代码使用的 byte 数组的长度是 85000 ,你测试的时候也可以使用更大的值,或者直接使用 int.MaxValue

在前面的 StackOverflow 文章中,有网友评论说,他们之前遇到的一个 StackOverflow 示例常常伴随着 OutOfMemory ,递归和这种方式有点类似,都是要一直创建新的对象,分配新的内存。

除此之外,还有哪些更简单的方式吗?欢迎补充

References

通过代码实现 `OutOfMemory的更多相关文章

  1. JVM中OutOFMemory和StackOverflowError异常代码

    1.Out of Memory 异常 右键Run As --->Run Configuration 设置JVM参数 -Xms20m -Xmx20m 上代码: /** * VM Args:-Xms ...

  2. 内存不足(OutOfMemory)的调试分析

    32位操作系统的寻址空间是4G,其中有2G被操作系统占用,也就是说留给用户进程的内存只有2G(其中还要扣除程序加载时映像占用的部分空间,一般只有1.6G~1.8G左右可以使用). 如果进程运行中需要申 ...

  3. 位图引起的内存溢出OutOfMemory解决方案

    一.问题描述:Android下的相机在独自使用时,拍照没有问题,通过我们的代码调用时,也正常,但是更换了不同厂商的平板,ROM由Android4.0变成了Android4.1后,拍照出现了OutOfM ...

  4. [改善Java代码]减少HashMap中元素的数量

    在系统开发中我们经常会使用HashMap作为数据集容器,或者是用缓冲池来处理,一般很稳定,但偶尔也会出现内存溢出的问题(OutOfMemory错误),而且这经常是与HashMap有关的.而且这经常是与 ...

  5. 【Java&Android开源库代码剖析】のandroid-smart-image-view

    Android应用开发已经进入到相对成熟的阶段,特别在国外,涌现出了各式各样的成熟稳定的开源库,供普通开发者使用.这种情况虽然极大加速了app开发的进程,但同时带来的问题是大多数普通开发者在使用这些开 ...

  6. Android Bitmap OutOfMemory 解决的方法

    在Android应用里,最耗费内存的就是图片资源.并且在Android系统中.读取位图Bitmap时,分给虚拟机中的图片的堆栈大小仅仅有8M.假设超出了.就会出现OutOfMemory异常 E/And ...

  7. Microsoft Edge 浏览器远程代码执行漏洞POC及细节(CVE-2017-8641)

    2017年8月8日,CVE官网公布了CVE-2017-8641,在其网上的描述为: 意思是说,黑客可以通过在网页中嵌入恶意构造的javascript代码,使得微软的浏览器(如Edege),在打开这个网 ...

  8. vb代码之------画一个半透明矩形

    入吾QQ群183435019 (学习 交流+唠嗑). 废话不说,咱们来看代码吧 程序结果运行如下 需要如下API 1:GdipCreateFromHDC 功能:创建设备场景相对应的绘图区域(相当于给设 ...

  9. Java编写高质量代码改善程序的151个建议

    第一章  Java开发中通用的方法和准则 建议1:不要在常量和变量中出现易混淆的字母: (i.l.1:o.0等). 建议2:莫让常量蜕变成变量: (代码运行工程中不要改变常量值). 建议3:三元操作符 ...

随机推荐

  1. IOC 原理

    SpringIOC实现原理 1. 依赖倒置 假设我们设计一辆汽车:先设计轮子,然后根据轮子大小设计底盘,接着根据底盘设计车身,最后根据车身设计好整个汽车.这里就出现了一个“依赖”关系:汽车依赖车身,车 ...

  2. jekins使用的坑

    1.日志打满 一个周末回来,服务器的磁盘就写满了 现象如下,最后是修改catalina脚本 添加了如下配置 ###jekins log problem#########export JAVA_OPTS ...

  3. Druid实现数据库连接用户密码加密

    使用ConfigFilter ConfigFilter的作用包括: 从配置文件中读取配置 从远程http文件中读取配置 为数据库密码提供加密功能 1 配置ConfigFilter 1.1 配置文件从本 ...

  4. 刷题 [网鼎杯 2018]Fakebook

    解题思路 首先登陆页面发现是这样的: 查看源码 源码很正常,也没有什么特别的 web目录扫描 我用的是dirmap工具扫描,扫描结果保存在一个txt文件中,结果可知没什么后台. robots.txt ...

  5. java安全编码指南之:敏感类的拷贝

    目录 简介 一个简单的SensitiveObject SensitiveObject的限制 对SensitiveObject的攻击 解决办法 简介 一般来说class中如果包含了私有的或者敏感的数据的 ...

  6. Pots(POJ - 3414)【BFS 寻找最短路+路径输出】

    Pots(POJ - 3414) 题目链接 算法 BFS 1.这道题问的是给你两个体积分别为A和B的容器,你对它们有三种操作,一种是装满其中一个瓶子,另一种是把其中一个瓶子的水都倒掉,还有一种就是把其 ...

  7. 【代码审计】JAVA代码审计

    分享一些Java安全相关文章,其中大部分都涉及到代码的分析与审计. 大家总是在找Java的代码审计的文章,但好像很多人选择性失明. 其实Java没有和PHP一样的简单,所以你觉得你看到的文章不是入门级 ...

  8. NOI 2012 【迷失游乐园】

    这道题,额,反正我是刚了2天,然后就萎了......(是不是觉得我很菜) 题目描述: 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩. 进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐 ...

  9. 对lambda表达式的字节码实现个人理解 - 简单描述

    暂且抛开具体的代码实现,谈谈个人的理解. 常规的方法调用,具体由哪条指令来执行,实际都是在JVM的规则中就定下来了,比如构造方法使用invokeSpecial,静态方法使用invokeStatic.现 ...

  10. 设置 eclipse C++ 版本

    gcc 版本 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC) 默认是使用 C++ 98 版本进行编译 设置 eclipse 中 C++ 的版本: Project  -& ...