一文搞懂5种内存溢出案例,内含完整源码

news/2025/3/18 12:26:18/文章来源:https://www.cnblogs.com/huaweiyun/p/18232455

本文分享自华为云社区《10分钟搞懂各种内存溢出案例!!(含完整源码,建议收藏)》,作者:冰 河。

作为程序员,多多少少都会遇到一些内存溢出的场景,如果你还没遇到,说明你工作的年限可能比较短,或者你根本就是个假程序员!哈哈,开个玩笑。今天,我们就以Java代码的方式来列举几个典型的内存溢出案例,希望大家在日常工作中,尽量避免写这些low水平的代码。

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

20210527082738369.png

定义主类结构

首先,我们创建一个名称为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); } } 
} 

点击关注,第一时间了解华为云新鲜技术~

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/720203.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SARscape5.7中DS-InSAR:E-PS操作说明

PS-InSAR方法测量PS点的形变,SBAS-InSAR方法测量分布式散射体DS(Distributed Scatters)的形变。随着技术的发展,在这一领域取得了许多研究进展,SARscape5.7版本开始,提供了能够同时提取PS和DS测量值的新方法,即增强型永久散射体(E-PS)和增强型短基线(E-SBAS)。 E-PS…

揭秘PW1558A:集成电源管理的6A双向限流过压保护IC

描述PW1558A 是一款先进的 28V 6A 额定双向负载开关, 提供过载、 短路、 输入电压浪涌、 过大冲击电流和过热保护, 为系统供电。 内置的 24mΩ超低 RDS(ON)电源开关有助于减少正常操作期间的功率损耗。 该设备具有两个输入/输出端口 VBUS1 和 VBUS2, 其绝对 MAX 大额定值为 …

物理隔离条件下文件交换的防泄密U盘,企业该如何选择?

对于网络安全要求高的企业和单位,往往采用物理隔离的方式进行网络建设,如政府单位、军工、科研所、航空航天企业、以及部分金融机构、医疗单位、电力企业、生物制药实验室等。但物理隔离后,仍然存在着隔离网间的数据交换需求,此时,仅能借助物理工具的方式进行文件交换,而…

第三届机器人、人工智能与信息工程国际学术会议(RAIIE 2024)

2024年第二届机器人、人工智能与信息工程国际学术会议(RAIIE 2024)将于2024年7月5-7日在新加坡举行。【ACM独立出版/Fellow大咖云集】2024年第二届机器人、人工智能与信息工程国际学术会议(RAIIE 2024) 2024 3rd International Symposium on Robotics, Artificial Intellig…

PyQT5之QRadioButton

import os.pathfrom PyQt5 import QtWidgets from PyQt5 import QtCore, QtGui import sys import cv2class ButtonPanel(QtWidgets.QWidget):def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)select_btn = QtWidgets.QPushButton("图像选择"…

TransGNN论文阅读笔记

TransGNN: Harnessing the Collaborative Power of Transformers and Graph Neural Networks for Recommender Systems论文阅读笔记 Abstract 存在的问题: ​ 目前基于 GNN 的方法仍面临着感受野有限和存在 "兴趣无关 "连接噪声的挑战。相比之下,基于Transformer的…

大型零售企业总部到分公司数据发放,有没有更优化的方案?

大型零售企业在市场经济中扮演重要角色,是保证基础商品生产、流通和供给的重要一环。随着企业发展,很多大型零售企业都会在全国、乃至全球各地开设分公司,用以降低生产和运营成本,更好地提供本地化服务。为了保证总部与分公司间信息通畅,同时,总部和分公司间的业务数据、…

UDP内网穿透和打洞原理的C语言代码实现

在典型的NAT穿透场景中,知道服务器端的公网IP和端口,但不知道客户端的公网IP,可以通过一些技巧来实现UDP打洞。可实现内网客户端与服务器相互UDP通信。v1.0 2024年6月5日 发布于博客园目录序言UDP打洞的原理应用场景基本理论代码实现udp_client_NAT.cudp_server_NAT.c结果参…

低代码智能通信:腾讯云短信助力,快速构建高效消息应用

前言 ​ 随着信息技术的飞速发展,现代社会对信息传达的及时性、准确性与便捷性要求越来越高。尤其在移动互联网时代,用户对于服务的体验要求不断提升,这促使各类网站、APP、小程序等服务平台必须持续优化其交互方式,以满足用户日益增长的需求。 ​ 在此背景下,短信作为一种…

.NET C# 程序自动更新组件

实现一个轻量级独立自动更新组件,可稍作修改集成到大家自己项目中,比如:WPF/Winform/Windows服务引言 本来博主想偷懒使用AutoUpdater.NET组件,但由于博主项目有些特殊性和它的功能过于多,于是博主自己实现一个轻量级独立自动更新组件,可稍作修改集成到大家自己项目中,比…

IC设计企业致力于解决的HPC数据防泄漏,到底该怎么做?

对于半导体IC设计企业来说,芯片设计、验证、仿真使用HPC环境现在已逐渐成为趋势,主要原因在于原来的工作流程存在较多的缺陷: 性能瓶颈:仿真、设计、验证、生产过程中,前端仿真需要小文件高并发低时延的读写和巨量元数据处理能力,后端仿真存储需要提供很大的读写带宽满足…