堆 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. windows安装trojan记录

    1.trojan 客户端安装教程 https://v2raytech.com/trojan-clients/ 2.chrome安装插件(crx文件)教程 https://www.jianshu.com ...

  2. iptables开启后造成本地套接字阻塞的问题

    前段时间,我使用iptables实现了针对IP地址与MAC地址的白名单功能,即将INPUT链的默认规则设为DROP: iptables -P INPUT DROP 这样就能拒绝一切外来报文.随后只需要 ...

  3. nginx简介,使用

    nginx是什么 nginx是一个开源的,支持高性能,高并发的www服务和代理服务软件. 支持高并发,能支持几万并发连接 资源消耗少,在3万并发连接下开启10个nginx线程消耗的内存不到200M 可 ...

  4. JDK1.8源码(八)——java.lang.ThreadLocal类

    https://www.cnblogs.com/xdd666/p/14734047.html ThreadLocal https://www.cnblogs.com/yanfei1819/p/1473 ...

  5. Lucene入门及实际项目应用场景

    导入maven依赖 <dependency> <groupId>org.apache.lucene</groupId> <artifactId>luce ...

  6. Djangoform组件——ModelForm的基本使用

    from django.contrib import admin from django.urls import path from app01 import views urlpatterns = ...

  7. CGLib 简析

    背景 JDK 动态代理存在的一些问题: 调用效率低 JDK 通过反射实现动态代理调用,这意味着低下的调用效率: 每次调用 Method.invoke() 都会检查方法的可见性.校验参数是否匹配,过程涉 ...

  8. 初学AOP小结

    Spring AOP理解 参考链接 AOP简介 AOP(面向切面编程),可以说时OOP的补充,使用OOP时,我们在日常编写代码的时候,一旦牵涉到大型一点的项目,项目不可或缺的事务处理,安全处理,验证处 ...

  9. vue实现拖动div元素

    html: <div id="app1"> <div v-drag class="drag"></div> <div ...

  10. Java 扫描识别条形码图片

    1.条形码扫描识别的实现方法及步骤 本文以Java代码示例介绍如何来扫描和识别条形码图片.这里使用免费条码工具 Free Spire.Barcode for Java,调用BarcodeScanner ...