堆 Heap

  一个 JVM 只有一个堆,堆也是 Java 内存管理的核心区域。在 JVM 启动时堆被创建,同时大小在启动时已设定好,堆是 JVM 管理最大的一块内存空间,其大小可以调节。

  • 堆的内存空间物理上可以不连续,逻辑上连续

  • 所有线程共享堆,甚至可以在堆中划分线程私有的缓冲区

  • 所有的对象实例和数组都存放在堆中,保存所有引用类型的真实对象。在栈帧中保存引用,引用指向对象或数组在堆中的位置

  • 方法结束后,堆中的对象不会被马上移除,只在垃圾回收时才被移除,因此堆是垃圾回收的重点区域

堆的内部结构

  JVM 采用分代收集算法,因此从 GC 的角度把堆内存在逻辑上分为新生代,老年代,元空间(JDK 8 以后)。

对象分配过程

  1. new 创建的对象放入 Eden 区,如果占用内存很大,直接分配到老年区

  2. 当 Eden 已满又需要创建对象时, MinorGC 进行垃圾回收

  3. MinorGC 回收时,把 Eden 和 ServivorFrom 中的幸存者复制到 ServivorTo,并将这些幸存者年龄+1,

  4. 清空Eden 和 ServivorFrom

  5. ServivorTo 和 ServivorFrom 互换

  6. 当某个对象到达指定年龄后,被调往养老区

  7. 在养老区内存不足时,触发 MajorGC

  8. 若在养老区执行 MajorGC 后依然空间不足,产生OOM异常

新生代

  新生代用于存放新生对象,大约占据 1/3 的堆空间,新生代又分为 Eden 区,ServivorFrom,ServivorTO 三个区。在 HotSpot 中,Eden 和两个 Servivor 空间占比 8:1:1。

  由于频繁创建对象,新生代会频繁触发 MinorGC 进行垃圾回收。MinorGC 采用复制算法

  绝大部分 Java 对象都在 Eden 区被创建,在新生代被销毁。

Eden 区

  Java 新对象的出生地,几乎所有的 Java 对象都在这里被创建。如果新对象占用内存很大,会直接分配到老年代。当 Eden 区内存不够时就会触发 MinorGC 进行垃圾回收。

ServivorFrom

  幸存0区,上一次GC的幸存者,这一次GC的被扫描者。

ServivorTo

  幸存1区,保留了一次 MinorGC 过程中的幸存者。

  两个幸存区是动态的概念,可以互相替换。

老年代

  主要存放应用程序中生命周期长的内存对象。老年代对象相对稳定,只有当老年代空间不足或无法找到足够大的连续空间给新对象时才会触发 MajorGC。

  MajorGC 采用标记清除算法:首先扫描一次所有老年代,标记存活对象,回收没有标记的对象。MajorGC 由于要扫描,因此耗时较长,且会产生内存碎片,需要进行合并整理。

元空间

  元空间与永久代最大的区别在于:元空间不在虚拟机中,直接使用本地内存。

  元空间存放类的元数据。元数据是指用来描述数据的数据,更通俗一点,就是描述代码间关系,或者代码与其他资源(例如数据库表)之间内在联系的数据。

为什么要将永久代替换为元空间?

  1. 永久代有一个 JVM 本身设置的固定大小上限,无法进行调整,而元空间使用的是直接内存,受本机可用内存的限制,内存溢出的几率更小

  2. 元空间里面存放的是类的元数据,而由系统的实际可用空间来控制,能加载更多的类

  3. 便于合并 HotSpot 和 JRockit 的代码,JRockit 中没有永久代,合并之后就没有必要额外的设置永久代了

堆空间垃圾回收

  堆空间的垃圾回收有三种机制,MinorGC,MajorGC,FullGC。每当开始垃圾回收时引发 STW(stop the world),会暂停其他用户线程,等回收结束,其他线程恢复。

MinorGC

MinorGC采用复制算法,MinorGC 的过程:复制->清空->互换。

  • 触发条件:Eden 区满,仅 Survivor 满时不会触发 MinorGC

  • 由于 Java 临时对象占比非常高,MinorGC 非常频繁,回收速度很快

MajorGC

MajorGC 采用标记清除算法,发生在老年代。

  • 出现 MajorGC,通常伴随至少一次的 MinorGC,新生代进入老年代,老年代空间不足时,触发 MajorGC

  • MajorGC 由于要扫描,因此耗时较长,且会产生内存碎片,需要进行合并整理

  • MajorGC 后,内存依然不足,则触发 OMM 异常

FullGC

FullGC 收集整个堆的垃圾,当准备要触发 MinorGC 时,如果发现统计数据说之前 MinorGC 的平均晋升大小比目前 MajorGC 剩余的空间大,则触发 FullGC。

  • 调用 System.gc() 时,系统建议执行 FullGC

  • FullGC 的暂停时间长,在调优中应当尽量避免

  • 很多时候 MajorGC 和 FullGC 混淆使用,需要理清是整堆回收还是仅老年代回收

JVM学习笔记——堆的更多相关文章

  1. JVM学习笔记(四)------内存调优【转】

    转自:http://blog.csdn.net/cutesource/article/details/5907418 版权声明:本文为博主原创文章,未经博主允许不得转载. 首先需要注意的是在对JVM内 ...

  2. JVM学习笔记(四)------内存调优

    首先需要注意的是在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提 ...

  3. java之jvm学习笔记十三(jvm基本结构)

    java之jvm学习笔记十三(jvm基本结构) 这一节,主要来学习jvm的基本结构,也就是概述.说是概述,内容很多,而且概念量也很大,不过关于概念方面,你不用担心,我完全有信心,让概念在你的脑子里变成 ...

  4. JVM学习笔记-JVM模型

    JVM学习笔记 == 标签(空格分隔): jvm 学习笔记全部来自于<深入理解java虚拟机>总结 jvm内存示意图 虚拟机栈(Java Virtual Machine Stacks): ...

  5. 【Java虚拟机】JVM学习笔记之GC

    JVM学习笔记二之GC GC即垃圾回收,在C++中垃圾回收由程序员自己来做,例如可以用free和delete来回收对象.而在Java中,JVM替程序员来执行垃圾回收的工作,下面看看GC的详细原理和执行 ...

  6. JVM 学习笔记记录

    JVM 学习笔记记录 Sun JDK 监控和故障处理工具 名称 主要作用 jps JVM Process Status Tool, 显示指定系统内所有的HotSpot虚拟机进程 jstat JVM S ...

  7. JVM学习笔记-第三章-垃圾收集器与内存分配策略

    JVM学习笔记-第三章-垃圾收集器与内存分配策略 tips:对于3.4之前的章节可见博客:https://blog.csdn.net/sanhewuyang/article/details/95380 ...

  8. JVM学习笔记-第六章-类文件结构

    JVM学习笔记-第六章-类文件结构 6.3 Class类文件的结构 本章中,笔者只是通俗地将任意一个有效的类或接口锁应当满足的格式称为"Class文件格式",实际上它完全不需要以磁 ...

  9. JVM学习笔记-第七章-虚拟机类加载机制

    JVM学习笔记-第七章-虚拟机类加载机制 7.1 概述 Java虚拟机描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被 ...

随机推荐

  1. RibbitMQ 实战教程

    # RabbitMQ 实战教程 ## 1.MQ引言 ### 1.1 什么是MQ `MQ`(Message Quene) : 翻译为 `消息队列`,通过典型的 `生产者`和`消费者`模型,生产者不断向消 ...

  2. 前端云原生,以 Kubernetes 为基础设施的高可用 SSR(Vue.js) 渲染微服务初探(开源 Demo)

    背景 笔者在逛掘金的时候,有幸看到掘友狼族小狈开源的 genesis - 一个可以支持 SSR 和 CSR 渲染的微服务解决方案.总体来说思想不错,但是基于 Kubernetes 云原生部署方面一直没 ...

  3. 轻松搞定webpack5.x

    源码地址:https://gitee.com/cyp926/webpack-project.git "webpack": "^5.46.0", "we ...

  4. Linux环境搭建及项目部署

    一. VMWare安装图解 1.点击下一步 2.接受条款,下一步 3.选择安装目录,不建议有中文目录和空格目录.下一步 4.下一步 5.这两个选项根据可以爱好习惯选择,下一步 6.安装 7.完成 9. ...

  5. [考试总结]noip模拟42

    开始给了一个简单的题目,但我还是没有珍惜. 一个简简单单的树形 \(dp\),然而因为取模却不知道该如何比较大小.. 其实可以取 \(log\),然后我就梦中惊坐起,然后想到了魔法少女lbw 淦 然后 ...

  6. Vs code自动生成Doxygen格式注释

    前言 ​ 程序中注释的规范和统一性的重要性不言而喻,本文就推荐一种在用vscode编写代码时自动化生成标准化注释格式的方法,关于Doxygen规范及其使用可查看博文 代码注释规范之Doxygen. ​ ...

  7. .net中使用JSON

    在.NET使用JSON作为数据交换格式 ASP.NET中JSON的序列化和反序列化 三种方式: 使用System.Web.Script.Serialization.JavaScriptSerializ ...

  8. Vue CSS模拟菜单点击变色

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  9. 一文搞懂Python Unittest测试方法执行顺序

    大家好~我是米洛! 欢迎关注我的公众号测试开发坑货,一起交流!点赞收藏关注,不迷路. Unittest unittest大家应该都不陌生.它作为一款博主在5-6年前最常用的单元测试框架,现在正被pyt ...

  10. 企业级镜像仓库 harbor

    企业级镜像仓库 harbor 前言 a. 本文主要为 Docker的视频教程 笔记. b. 环境为 CentOS 7.0 云服务器 c. 上一篇:跨 Docker 宿主机网络 overlay 类型 h ...