堆 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. mysql复制内容到一张新表

    -- 1.复制表结构及数据到新表 CREATE TABLE 新表 SELECT * FROM 旧表 -- 2.只复制表结构到新表 CREATE TABLE 新表 SELECT * FROM 旧表 WH ...

  2. 刷题-力扣-剑指 Offer 42. 连续子数组的最大和

    剑指 Offer 42. 连续子数组的最大和 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de ...

  3. mysql最强

    MYSQL 与mysql第一次亲密接触 数据库相关概念 一.数据库的好处 二.数据库的常见概念 ★ 三.数据库存储数据的特点 四.常见的数据库管理系统 MYSQL的介绍 一.MySQL的背景 二.My ...

  4. netty系列之:自建客户端和HTTP服务器交互

    目录 简介 使用客户端构建请求 accept-encoding server解析HTTP请求 总结 简介 上一篇文章,我们搭建了一个支持中文的HTTP服务器,并且能够从浏览器访问,并获取到相应的结果. ...

  5. “类型思维”之Typescript,你掌握了吗?

    (一)背景 JavaScript是一门动态弱类型语言 对变量的类型非常宽容 而且不会在这些变量和它们的调用者之间建立结构化的契约. 试想有这么几个场景: 1: 你调用一个别人写的函数,但是这个人没有写 ...

  6. C# - 习题01_写出程序的输出结果a.Fun2(b)、b.Fun2(a)

    时间:2017-08-23 整理:byzqy 题目:请写出下列程式的结果: 文件:A.cs 1 using System; 2 3 namespace InterView 4 { 5 public c ...

  7. yum命令报错File "/usr/bin/yum", line 30 except KeyboardInterrupt, e:

    使用yum命令报错File "/usr/bin/yum", line 30 except KeyboardInterrupt, e: 问题出现原因:yum包管理是使用python2 ...

  8. git 提交本地项目

    在新文件夹中] 1.右键 git bash here,执行 2.git init 生成.git文件,存在则跳过 依次执行 1.git add . 2.git commit -m "提交信息& ...

  9. excel中if函数的用法

    IF函数有三个参数,语法如下: =IF(条件判断, 结果为真返回值, 结果为假返回值) 第一参数是条件判断,比如说"A1="百度""或"21>3 ...

  10. 使用Visual Studio Code 开发 ESP8266

    使用Visual Studio Code 开发 ESP8266 ESP8266+ArduinoIDE+VSCode开发ESP8266. 首先说明一下ESP8266并不是某一WiFi模块的名字(我以前是 ...