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

📫作者简介:小明java问道之路2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于知名金融公司后端高级工程师。

        

📫 热衷分享,喜欢原创~ 关注我会给你带来一些不一样的认知和成长。

        

🏆 2022博客之星TOP3 | CSDN博客专家 | 后端领域优质创作者 | CSDN内容合伙人

🏆 InfoQ(极客邦)签约作者、阿里云专家 | 签约博主、51CTO专家 | TOP红人、华为云享专家

        

🔥如果此文还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主~ 


🍅 文末获取联系 🍅  👇🏻 精彩专栏推荐订阅收藏 👇🏻

专栏系列(点击解锁)

学习路线(点击解锁)

知识定位

🔥Redis从入门到精通与实战🔥

Redis从入门到精通与实战

围绕原理源码讲解Redis面试知识点与实战

🔥MySQL从入门到精通🔥

MySQL从入门到精通

全面讲解MySQL知识与企业级MySQL实战

🔥计算机底层原理🔥

深入理解计算机系统CSAPP

以深入理解计算机系统为基石,构件计算机体系和计算机思维

Linux内核源码解析

围绕Linux内核讲解计算机底层原理与并发

🔥数据结构与企业题库精讲🔥

数据结构与企业题库精讲

结合工作经验深入浅出,适合各层次,笔试面试算法题精讲

🔥互联网架构分析与实战🔥

企业系统架构分析实践与落地

行业最前沿视角,专注于技术架构升级路线、架构实践

互联网企业防资损实践

互联网金融公司的防资损方法论、代码与实践

🔥Java全栈白宝书🔥

精通Java8与函数式编程

本专栏以实战为基础,逐步深入Java8以及未来的编程模式

深入理解JVM

详细介绍内存区域、字节码、方法底层,类加载和GC等知识

深入理解高并发编程

深入Liunx内核、汇编、C++全方位理解并发编程

Spring源码分析

Spring核心七IOC/AOP等源码分析

MyBatis源码分析

MyBatis核心源码分析

Java核心技术

只讲Java核心技术

本文目录

本文导读

一、栈内存溢出

1、死递归

2、线程太多

二、堆内存溢出

1、初始对象太大

2、对象没有回收

3、常量池溢出

三、方法区内存溢出

四、直接内存溢出

总结


本文导读

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

内存溢出有几种类型,栈溢出(程序所要求的栈深度过大)、堆溢出(创建对象时如果没有可以分配的堆内存、对象没有被回收)、方法区溢出(Class对象未被释放,Class对象占用信息过多,有过多的Class对象)、直接内存溢出(分配的本地内存大小大于JVM的限制)。

一、栈内存溢出

1、死递归

线程请求的栈深度大于虚拟机所允许的最大深度,将抛出 StackOverflowError,可以写一个死递归程序触发。

Java的栈空间默认是1M大小,可以通过-Xss 调整

public class StackOverFlow {public void test(){test();//死递归}public static void main(String[] args)throws Throwable {StackOverFlow javaStack = new StackOverFlow();javaStack.test();}
}

2、线程太多

线程太多会导致栈溢出,抛出 OutOfMemoryError,例如1个方法运行中的对象占用1M内存。同时5000+个线程运行这个方法,如果机器的内存小于5G的话,那么也会发生内存溢出,这种情况会抛出OOM异常。

public class StackOutOfMemoryError {public static void main(String[] args) {StackOutOfMemoryError test = new StackOutOfMemoryError ();test.oomMethod();}public void oomMethod(){while(true){new Thread(new Runnable() {@Overridepublic void run() {loopMethod();}}).start();;}}private void loopMethod(){while(true){}}
}

二、堆内存溢出

1、初始对象太大

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

堆内存可以通过设置JVM初始堆空间和最大堆空间,堆溢出生成快照:

-Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError

/*** VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError*/
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));}
}

2、对象没有回收

在方法执行中,回收效率不足2%,抛出 OutOfMemoryError: GC overhead limit exceeded。

/**** VM Args:-Xms10m -Xmx10m  -Xmn5m -XX:+PrintGCDetails   堆的大小10M* 堆内存溢出*/
public class HeapOom {public static void main(String[] args) {List<Object> list = new LinkedList<>(); //在方法执行的过程中,它是GCRootsint i =0;while(true){i++;if(i%10000==0) System.out.println("i="+i);list.add(new Object());}}
}

3、常量池溢出

JDK 1.8中 PermSize 和 MaxPermGen 已经无效,JDK 1.7 和 1.8 将字符串常量由永久代转移到堆中,并且 JDK 1.8 中已经不存在永久代的结论。

对象实际存储在堆上面,最终会产生堆内存溢出(java.lang.OutOfMemoryError: Java heap space),将堆内存设置为:-Xms5m -Xmx5m。

public class ConstantPoolOOMTest {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);}}
}

三、方法区内存溢出

方法区溢出为,java.lang.OutOfMemoryError: Metaspace,一般发生在动态语言,因为动态语言编译后会放在方法区。

在经常动态生产大量Class的应用中,CGLIb字节码增强,动态语言,大量JSP(JSP第一次运行需要编译成Java类),基于OSGi的应用(同一个类,被不同的加载器加载也会设为不同的类)。如果方法区内存不够大的话也会发生java.lang.OutOfMemoryError: Metaspace溢出。

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);// 借助CGLib直接操作字节码,生成大量的动态类enhancer.setCallback(new MethodInterceptor() {@Overridepublic 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{}
}

四、直接内存溢出

​直接内存溢出( java.lang.OutOfMemoryError: Direct buffer memory)分配的本地内存大小大于JVM的限制。NIO会使用到直接内存,可以通过NIO来模拟。

设置参数: -XX:MaxDirectMemorySize=100m 

/*** VM Args:-XX:MaxDirectMemorySize=100m* 限制最大直接内存大小100m* 直接内存溢出*/
public class DirectOom {public static void main(String[] args) {// 直接分配128M的直接内存(100M)ByteBuffer bb = ByteBuffer.allocateDirect(128*1024*1204);}
}

总结

内存溢出有几种类型,栈溢出(程序所要求的栈深度过大)、堆溢出(创建对象时如果没有可以分配的堆内存、对象没有被回收)、方法区溢出(Class对象未被释放,Class对象占用信息过多,有过多的Class对象)、直接内存溢出(分配的本地内存大小大于JVM的限制)。

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

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

相关文章

Golang 中的 Context 包

简介 今天&#xff0c;我们将讨论 Go 编程中非常重要的一个主题&#xff1a;context 包。如果你现在觉得它很令人困惑&#xff0c;不用担心 — 在本文结束时&#xff0c;你将像专家一样处理 context&#xff01; 想象一下&#xff0c;你在一个主题公园&#xff0c;兴奋地准备…

界面控件DevExtreme图表和仪表(v23.1) - 新功能(Angular,React,Vue,jQuery)

本文将为大家总结下DevExtreme在v23.1版本中发布的一些与图表和仪表盘相关的功能。 DevExtreme拥有高性能的HTML5 / JavaScript小部件集合&#xff0c;使您可以利用现代Web开发堆栈&#xff08;包括React&#xff0c;Angular&#xff0c;ASP.NET Core&#xff0c;jQuery&#…

2023年【汽车驾驶员(中级)】免费试题及汽车驾驶员(中级)考试试卷

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年【汽车驾驶员&#xff08;中级&#xff09;】免费试题及汽车驾驶员&#xff08;中级&#xff09;考试试卷&#xff0c;包含汽车驾驶员&#xff08;中级&#xff09;免费试题答案和解析及汽车驾驶员&#xff08;…

文心一言 VS 讯飞星火 VS chatgpt (135)-- 算法导论11.3 1题

一、用go语言&#xff0c;假设我们希望查找一个长度为 n 的链表&#xff0c;其中每一个元素都包含一个关键字k并具有散列值h(k)。每一个关键字都是长字符串。那么在表中查找具有给定关键字的元素时&#xff0c;如何利用各元素的散列值呢? 文心一言&#xff1a; 在Go语言中&a…

【JAVA学习笔记】70 - 反射

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter23/src 反射 一、反射的引出 package com.yinhai.reflection.question;import com.yinhai.Cat;import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IO…

jetsonTX2 nx配置tensorRT加速yolov5推理

环境说明 Ubuntu 18conda环境python3.9cuda10.2&#xff0c;硬件平台是Jetson tx2 nx 前提你已经能运行YOLOV5代码后&#xff0c;再配置tensorRT进行加速。 目前只试了图片检测和C打开USB摄像头进行视频检测&#xff0c;希望是使用python配合D435i深度相机来实现检测&#xff…

Qt 自定义全局悬浮置顶按钮

Qt 自定义全局悬浮置顶按钮 效果 使用示例 ResetButton* resetBtn; resetBtn new ResetButton(); resetBtn->show(); resetBtn->move(QPoint(1000, 800)); connect(resetBtn, &ResetButton::clicked, this, &MainWindow::Reset);自行加入图片&#xff0c;透明…

【QT】飞机大战

0 项目简介 飞机大战是我们大家所熟知的一款小游戏&#xff0c;本教程就是教大家如何制作一款自己的飞机大战 首先我们看一下效果图 玩家控制一架小飞机&#xff0c;然后自动发射子弹&#xff0c;如果子弹打到了飞下来的敌机&#xff0c;则射杀敌机&#xff0c;并且有爆炸的特…

Unity 调用自己封装好的DLL库

因为做项目时会用到很多重复的方法&#xff0c;每次都重新写有点浪费时间&#xff0c;就可以将这些方法封装成DLL类库&#xff0c;用的时候直接引入调用就行。 首先在VS里面创建类库文件 注&#xff1a;.NET Framework要选3.5以下 然后定义好命名空间名字和类名就可以写自己要…

在 Vue3 中使用 mitt 进行组件通信

npm 包地址 mitt 是一个轻量级的 JavaScript 事件触发器&#xff0c; 只有200b。有基本的事件触发、订阅和取消订阅功能&#xff0c;还支持用命名空间来进行更高级的事件处理。 功能特点&#xff1a; Microscopic —— weighs less than 200 bytes gzippedUseful —— a wil…

elemenui的Upload上传整合成数组对象

1. 普通直接上传 <el-upload action"" :before-upload"doBeforeUpload"><el-button type"success" size"mini">导入</el-button></el-upload> methods:{doBeforeUpload(file) {let reader new FileReader(…

mysql的主从复制,读写分离

主从复制&#xff1a;主mysql的数据&#xff0c;新增&#xff0c;修改&#xff0c;表里的数据都会同步到从mysql上 主从复制的模式&#xff1a; 1 异步复制 mysql 的最常用的复制&#xff0c;只要执行完&#xff0c;客户端提交事务&#xff0c;主mysql 会立即把结果返回给从…