堆 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. ubuntu下配置JDK的一些坑点

    ubuntu下配置JDK的一些坑点 在centos下的JDK配置: 在ubuntu下的话,要修改两个地方: 在/etc/enviornment中配置! 在/etc/profile中配置! 写在最后: ...

  2. ProjectEuler 009题

    题目: A Pythagorean triplet is a set of three natural numbers, a b c, for which, a2 + b2 = c2 For exam ...

  3. Flink与Strom两个框架的对比分析

    一.Flink与Storm两个框架的对比 二.Flink 的特性 1.高吞吐.低延迟.高性能 2.支持带事件的窗口(window) 操作:time.count.session.data-driven ...

  4. Go定时器--Timer

    目录 前言 Timer 定时器 简介 使用场景 1. 设定超时时间 2. 延迟执行某个方法 Timer对外接口 1. 创建定时器 2. 停止定时器 3. 重置定时器 其他接口 1. After() 2 ...

  5. Java如何调用C语言程序,JNI技术

    Java为什么要调用C语言编写的程序因为涉及操作系统底层的事件,Java是处理不了的,例如用户上传一个视频文件,需要后台给视频加上水印,或者后台分离视频流和音频流,这个事Java就做不了,只能交给C语 ...

  6. 基于Bootstrap v4.1.1 & Bootstrap-table-1.14.1实现数据瀑布流

    基于Bootstrap-table-1.14.1实现数据瀑布流 HTML代码 <div id="AvgWaitAndAvgTimeServiceTimeData_hall"& ...

  7. K8S资源编排(yaml)

    1.yaml的格式 2.yaml的组成部分 3.yaml常用字段的含义 4.yaml编写方式 (1)方式一:使用kubectl create命令生成yaml文件,然后修改 (2)方式2:在已经部署好的 ...

  8. Python习题集(九)

    每天一习题,提升Python不是问题!!有更简洁的写法请评论告知我! https://www.cnblogs.com/poloyy/category/1676599.html 题目 已知一个数列:1. ...

  9. openswan源码ubantu下编译、安装、基本环境搭建

    openswan的编译过程 文章目录 openswan的编译过程 1. 下载源码: 2. 在虚拟机上解压后编译: 2.1 查看INSTALL文件 2.2 查看文件buildlin.sh文件 3. 查看 ...

  10. Storm近年的发展

    storm作为第一款大数据领域的流式计算引擎,在2013年推出之后风头一时无二.后续虽然有spark streaming也作为流式计算的引擎,但storm依然在流式计算的江湖占有稳定的地位.直到201 ...