什么是内存溢出?在哪些区域会发生内存溢出?回答这个问题,我们需要先看一看Java代码是怎么运行的。现在计入说我们写了一个 HelloWorld.class

1
2
3
4
5
6
public class HelloWorld {public static void main(String[] args){String message = "Hello World";System.out.println(message);}
}

我们来分析一下这段代码的运行情况:

  1. 源文件 HelloWorld.java 将会被编译成可执行文件 HelloWorld.class
  2. 类加载加载可执行文件到 Metaspace,Metaspace 保存类的基本信息,如果加载太多就会 OOM
  3. Java是多线程的,运行代码的时候会启动一个线程。main()是Java程序的入口,首先会启动一个 main 线程。每个线程都有 Java 虚拟机栈,每执行一个方法都会有一个栈帧入栈,栈帧中包含参数、局部变量、返回值地址等信息。如果代码层次太深,不断有方法入栈却没有出栈,Java虚拟机栈就会 OOM。
  4. 栈中的局部变量如果是一个对象,那就会在初始化的时候在堆中创建对象。堆中创建的对象过多就会触发 GC,GC 的速度赶不上新建对象的速度也会发生 OOM。

从 Java 代码的运行过程来看,有三个区域会发生 OOM,它们分别是:Metaspace、Java 虚拟机栈、堆内存。

Metaspace 是如何溢出的?

Metaspace 中会加载类,保存各种类信息,它的大小可以通过 -XX:MetaspaceSize=512m-XX:MaxMetaspaceSize=512m 来设置。

当我们不断地创建类,不断地创建类,把 Metaspace 的内存都给占满了。这个时候就会触发 Full GC,Full GC 一般会顺带着进行 Minor GC 回收年轻带,也会进行 Old GC 回收老年代。

如果 Full GC 回收 Metespace 中的空间之后,任然无法存放新建的对象,此时 OOM 就会发生了。

不过 Metaspace 一般很少发生 OOM,如果发生了一般是出于下面两个原因:

  1. 上线系统的时候对 Metaspace 区域直接用默认的参数,即根本不设置其大小。默认的Metaspace区域可能才几十MB,对于稍微大型的系统,他自己有很多类,还依赖了很多外部的jar包,几十MB的Metaspace很容易就不够了。
  2. 写代码的时候用到了类似与 cglib 的动态代理技术,代码写得不好就会导致创建太多的类。

线程中的栈是如何溢出的?

虚拟机中的栈内存也是有限的,我们调用方法的时候会创建一个栈帧,紧接着方法入栈。如果一个线程一直调用方法入栈,栈内存终归是要满的,此时线程的栈中就会发生 OOM。

发生这种情况一般就是代码除了问题,比如写了个递归调用,和 Metaspace 的内存溢出一样,也很少发生。

堆内存是如何溢出的?

最常见的就是堆内存溢出的问题了。堆内存有限的情况下,不断创建对象并触发 GC,但是 GC 过后任然有大量大象存活,此时还要放入大量新的对象,这就会导致堆内存溢出问题。

一般来说对内存溢出有这样两个场景:

  1. 高并发场景下,请求量太大,创建了大量新的对象,且这些都是有用的、存活的。堆中无法放入更多对象就会导致堆内存溢出
  2. 内存泄漏问题,长生命周期的对象引用了大量短生命周期的对象,没有及时取消对它们的引用,导致 GC 无法回收这些理应被回收的对象,就导致了堆内存溢出

什么是内存溢出?在哪些区域会发生内存溢出?相关推荐

  1. jvm中有哪些内存区域会发生内存溢出

    1.方法区溢出 第一种原因:上线的时候MetaSpace区域直接用默认的参数,即根本不设置其大小,这会导Meta Space区域可能才几十M而已或者设置的比较小,此时对于一个稍微大型系统,因为他有很多 ...

  2. unity如何检测内存泄漏_如何排查Java内存泄漏?看懂这一篇就够用了

    原文:https://www.toptal.com/java/hunting-memory-leaks-in-java 作者:Jose Ferreirade Souza Filho 译者:Emma来源 ...

  3. ie传递给系统调用的数据区域太小_内存区域与内存溢出异常

    自动内存管理机制 运行时数据区:Java虚拟机定义了在程序执行期间使用的各种运行时数据区域.其中一些数据区域是在Java虚拟机启动时创建的,仅在Java虚拟机退出时销毁.其他数据区域是每个线程所占的空 ...

  4. JVM面试题整理-Java内存区域与内存溢出异常、垃圾收集器和内存分配策略

    参考: https://blog.csdn.net/zd836614437/article/details/64126826 https://blog.csdn.net/u011225629/arti ...

  5. 《深入理解JAVA虚拟机》详细解读(第二章 ):JAVA内存区域与内存溢出异常

    目录 一.JAVA内存区域与内存溢出异常 1. 概述 2. 运行时数据区域 2.1 程序计数器 2.2 Java虚拟机栈 2.3本地方法栈 2.4 堆 2.5 方法区 2.6 运行时常量池 2.7直接 ...

  6. 深入理解Java虚拟机——第二章——Java内存区域与内存溢出异常

    运行时数据区域 Java虚拟机运行时数据区域 程序计数器 程序计数器可以看做是当前线程所执行的字节码的行号指示器.字节码解释器工作时就是通过改变这个计数器的值来选取下一条所需要执行的字节码指令,分支. ...

  7. java内存区域与内存溢出异常_Java内存区域与内存溢出异常

    Java的内存管理是一个老生常谈的问题,虽然Java号称可以自动管理自己的内存,使程序员从内存管理的围墙解放出来,但是一连串的内存泄漏和溢出方面的问题,使得我们不得不去深入了解Java的内存管理机制. ...

  8. JVM最佳学习笔记一---Java内存区域与内存溢出异常

    2019独角兽企业重金招聘Python工程师标准>>> 前言 本笔记参照了周志明<深入理解Java虚拟机:JVM高级特性与最佳实践>第三版,读完之后受益匪浅,让我对Jav ...

  9. 图解Java内存区域及内存溢出异常

    图解 Java 内存区域及内存溢出异常 在阅读 <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版) >后,为了加深对 Java 内存区域的印象及理解,特意做成了思维导图. 名词解 ...

最新文章

  1. 不可思议!英伟达新技术训练NeRF模型最快只需5秒,代码已开源
  2. bootstrap简单登录界面
  3. Java线程:新特征-条件变量(转)
  4. Tp3.2在nginx下隐藏index.php文件
  5. docker启动.NET3.1与5.0的包
  6. Python第四章__装饰器、迭代器
  7. LI标签在Ul中居中显示
  8. android usb多个,android、windows上多个USB Camera同时使用实验小结
  9. 西南大学校园GIS平台
  10. Redis基础(十一)——缓存穿透和缓存雪崩
  11. remoting 最简单的一个例子
  12. Swift语言入门学习
  13. 一名普通医护人员的抗疫日志
  14. Oracle数据库的整体结构
  15. Alphasense B4系列PPB 级空气质量传感器应用
  16. 20世纪英国癌症三级预防研究
  17. 攻防世界——pwn_forgot
  18. 内江求是中学计算机应用有哪些,内江市求是职业技术学校(内江市求是中学)官网/招生网2020网址...
  19. 2.1 Linux基础(命令-文件系统)
  20. 医用计算机学习心得,计算机学习心得体会范文

热门文章

  1. 故障分析 | Greenplum Segment 故障处理
  2. 笔记本进入pe却看不到计算机硬盘,11代cpu笔记本进pe看不到硬盘解决方法(PE完美解决)...
  3. 智能卡水表管理系统功能介绍
  4. 福州大学计算机专硕考纲,2020年福州大学硕士研究生招生考试考试大纲
  5. 【全志T113-S3_100ask】6-编写IIC驱动GY-302(twi)
  6. Linux函数调用劫持的方法总结(带图)
  7. c语言考试系统设计报告,C语言课程设计(单项选择题标准化考试系统)报告
  8. 动态规划题集(转载)
  9. 开发者证书、授权文件的管理
  10. 【移动网络】Ch. 2 移动网络基本原理 (Part1. 无线信道与数据率)