Marvel-Site Marvel-Site
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)

Marvel

吾必当乘此羽葆盖车
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)
  • Java

    • Java基础

    • Java进阶

    • Java容器

    • Java并发编程

    • Java虚拟机

      • JVM与Java体系结构
      • JVM内存区域详解
      • JVM类的加载过程详解
      • JVM创建对象过程
      • JVM垃圾回收详解
      • JVM参数设置
      • JVM性能调优工具
      • 内存泄漏与内存溢出
      • 常见面试题

    • 计算机基础

    • 框架|中间件

    • 架构

    • 后端
    • Java
    • Java虚拟机
    Marvel
    2022-07-13
    目录

    内存泄漏与内存溢出

    # 内存泄漏与内存溢出

    # 1 什么是内存泄漏?

    指一个不再被程序使用的对象或变量一致占据在内存中。

    内存泄漏的情况1:程序员创建了一个对象,以后一直不再使用这个对象,这个对象却一直被引用,即这个对象无用但是却无法被垃圾回收器回收,这就是java中可能出现内存泄漏的情况。例如,缓存系统,我们加载了一个对象放在缓存中(例如放在全局map对象中),然后一直不再使用它,这个对象一直被缓存引用,但却不再被使用。

    内存泄漏情况2:当一个对象被存进HashSet集合中,就不能修改这个对象中那些参与计算哈希值的字段。否则,修改后的哈希值与最初存储在HashSet集合中的哈希值不同,这种情况下,使用contains方法无法在HashSet中检索到对象,这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄漏。

    public class MemoryLeakTest {
        public static void main(String[] args) {
            HashMap<String, Integer> map = new HashMap<>();
            String s = "abc";
            map.put(s, 1);
            System.out.println(map.get(s));  // 1
            System.out.println(map.size());  // 1
            s = "aaa";
            System.out.println(map.get(s));  // null
            System.out.println(map.size());  // 1
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    # 2 什么是内存溢出(OOM)?哪些区域会OOM?

    指程序运行过程中无法申请到足够的内存而导致的一种错误。常见情况:OutOfMemeryError异常。

    1. 虚拟机栈和本地方法栈溢出
      • 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError
      • 如果虚拟机在扩展时无法申请到足够的内存空间,将抛出OutOfMemoryError
    2. 堆溢出
      • 是否出现内存泄漏,可通过工具查看泄漏对象到GC ROots的引用链。
      • 如果没有内存泄漏,查看虚拟机的参数(-Xmx于-Xms)的设置是否适当,
    3. 方法区溢出
    4. 运行时常量池溢出

    # 3 谈谈对OOM的认识

    OOM:OutOfMemeryError,是错误,不是异常

    image-20220621210931483
    • java.lang.StackOverflowError——栈深度大于虚拟机所允许的最大深度,无限递归。
    • java.lang.OutOfMemoryError: Java heap space——堆内存不够了
    • java.lang.OutOfMemoryError: GC overhead limit exceeded——GC 的回收时间过程,超过 98% 的时间都用来 GC 且回收了不到 2% 的堆内存。
    • java.lang.OutOfMemoryError: Direct buffer memory image-20220621212232555
    • java.lang.OutOfMemoryError: unable to create new native thread image-20220621212851031
    • java.lang.OutOfMemoryError: Metaspace——元空间满了

    # 3 内存溢出的原因?

    1. 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
    2. 集合类中有对对象的引用,使用完后为清空,使得JVM不能回收;
    3. 代码中存在死循环或循环产生过多重复的对象实体。
    4. 启动参数内存值设定的过小。

    # 4 栈溢出的原因和解决办法?

    原因:

    1. 大量的递归调用,在不断的压入栈帧,造成站容量超过内存而导致溢出。
    2. 由于分配了过大的局部变量。

    解决办法:

    1. 递归转化为非递归
    2. 使用静态对象替换非静态局部变量
    3. 增加栈堆的大小
    编辑 (opens new window)
    #Java#JVM
    上次更新: 2023/08/20, 21:21:52
    JVM性能调优工具
    海量数据处理

    ← JVM性能调优工具 海量数据处理→

    最近更新
    01
    位运算
    05-21
    02
    二叉树
    05-12
    03
    Spring三级缓存解决循环依赖
    03-25
    更多文章>
    Theme by Vdoing | Copyright © 2022-2024 Marvel
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式