本文阐述hotspot虚拟机对堆的规划方式

GC按照回收范围分为两种GC
1.minor GC(也叫Young GC)只能回收新生代,minor读作[ˈmaɪnər] ,译为少数的,速度非常快
2.full GC(也叫Major GC)回收整个堆(老年代+新生代),速度较慢,与年轻代的minor GC相比速度差至少十倍

笔记:一切的调优,最终目的都是减少full GC
笔记:full GC慢的原因主要是标记的对象比较多,标记对象的时候比较耗时间

1.新生代

装的全都是新建的对象

单词survivor读作 [sərˈvaɪvər]译为幸存者,DNF游戏里有一个SS武器,叫做幸存者的奥秘,读作The mystery of survivors

新生代又具体分三个小区

1).新生代的eden区:默认占新生代总大小8/10,只要new一个对象,就会到eden区
2).新生代的survivor0区(from区):最开始from和to是没有数据的,当eden区满了之后,会触发minor GC,这个时候存活下来的对象会放到survivor0区
3).新生代的survivor1区(to区):当再次出发minor GC的时候,会清空eden+surivivor0区,将存活的对象都放到survivor1中

日记:survivor0和survivor1将会轮流加上eden被清理,存活的对象放入那个没清理的survivor区,假设现在清理的是s0+eden,那么存活的对象会放到s1,下次再清理,就清理s1+eden,存活的对象会放到s0
eden:survivor0:survivor1的比例默认等于8:1:1,知道这个比例很重要,优化的时候会用到

2.老年代

每当有一批新对象进入老年代,jvm都会记录每一批对象总和的平均大小,比方说第一次GC有3个对象进入了老年代,总大小是10M,第二次GC有2个对象进入了老年代,总大小是5M,那么每次GC的平均大小为7.5M(与个数无关),假设这个平均值是AVE,此时AVE=7.5

有以下5种条件可以使对象进入老年代(此处尤为重要,一定要死记硬背下来)

(1) 多次(默认15次)垃圾回收之后,依然存活的对象,会进入老年代
(2) 有新对象产生,minor GC之后,新生代依然放不下,则放入老年代
(3) 如果new出来的是一个大对象,则直接放入老年代(通过虚拟机启动参数来定义多大才叫大对象,且只在Serial和ParNew这两个垃圾收集器下有效,关于垃圾收集器的介绍可以点击这里)
(4) 动态年龄推断:预测一个对象是否有可能会存活相当长的一段时间,如果该对象很有可能存活很久,则应该尽早的进入老年代,不应该在新生代来回移动,具体算法如下:当minor GC之后,年轻代存活的对象总大小大于survivor的50%(一定是50,是jvm定死的),则从这一批对象中找到最大年龄n,然后将该survivoer区所有年龄等于n的对象,都挪到老年代

示例:Eden=8,Surivivoer0=1,此时Eden+Surivivoer0=9,假设回收之后,Eden+Surivivoer0=3,这个3大于Surivivoer的一半0.5,所以从3中找到年龄最大的对象,将该对象和与该对象年龄相等的对象,都挪到老年代

注意: 有其他文章或者博客说 “如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代”,这是不对的,可能是翻译错误,千万不要被“相同年龄”误导,正确的说法就是我的文章中说的“本次挪动的这批对象”,而不分年龄

(5) 老年代空间分配担保:提供一个算法,该算法担保这批对象一定能放到老年区,当然也会发生堆溢出(OOM),只是通过这个算法保证了不OOM的情况下,一定能放到老年区

假设老年代剩余空间大小是SS(surplus space)
执行minor GC之前,会按照下面的伪代码逻辑来决定是否执行full GC

//老年代极有可能放不下本次回收后存活的对象,所以执行full GC
if(SS < AVE){// AVE在上文中已经说过了//则执行full GC
}else{// 正常执行minor GC
}

上述JVM的算法并不是一定放不下存活对象,而是从大概率上减少不必要的GC
注:JDK1.8之前对老年代空间分配担保需要HandlePromotionFailure参数设置,都2021年了,所以就不需要考虑这些了

分代思想的好处在于新生代回收采用适合新生代特点的算法,老年代回收的时候采用适合老年代特点的算法,因为没有一种算法同时适合所有特点,正所谓二者不可兼得

3.卡表(card table)

Young GC只能回收年轻代,假设没有通过GC ROOT跟找到一个年轻代的对象A是否存活,但是A对象被老年代的对象引用,那么该如何决定A是否是一个垃圾呢?除了扫描老年代之外,没有其他办法,如果扫描整个老年代,那么分代思想的意义又没了,所以使用card table,来扫描部分老年代

卡表理论:如果将老年代内存被划分成一些内存页,并对这些内存页进行编号,然后将这些编号与bitmap关联起来,假设bitmap是下面这样子的,则表示老年代第3个内存页中,有某个对象,被新生代的对象引用了

上述的bitmap被赋值的过程,是每次对一个老年代对象A的字段B赋值的时候(GC屏障),JVM都会判断这个B所在的内存是否是处于新生代,如果是,则将bitmap对应的位置1,这样,在进行可达性分析的时候,就不用扫描所有的老年代内存页,只需要扫描老年代为1的内存页即可

重点:虽然bitmap实现卡表的优势显而易见,但是Hotspot并没有采用bitmap,原因是单个指令位操作虽然快,但是操做bitmap需要好几个机器指令,总体来说也不快,最终采用的是byte数组,用空间换时间

4.堆的优化

整理:根据一个业务链的长度,算出所有对象的大小,然后再乘以几十(一般都是乘以30),这就是eden区的大小
提高机器配置,同时设置年轻代大一点,如果太小,那么gc就会频繁,gc频繁就会导致年龄增长过快(也会频繁STW),增长过快就会导致老年代对象积累的快,问题是如果一个对象刚进老年代,就没用了,那么就占内存

Java-虚拟机-堆的内存规划/新生代/老年代/卡表相关推荐

  1. Java架构学习(十二)java内存结构新生代老年代JVM参数调优堆内存参数配置解决堆栈溢出

    JVM参数调优与垃圾回收机制 一.java内存结构 Java内存模型:是多线程里面的,jmm与线程可见性有关 Java内存结构:是JVM虚拟机存储空间. Java内存结构图 Java内存机构分为:方法 ...

  2. Java虚拟机堆的内存分配和回收

    java内存分配和回收,主要就是指java堆的内存分配和回收.java堆一般分为2个大的区域,一块是新生代,一块是老年代.在新生代中又划分了3块区域,一块eden区域,两块surviver区域.一般称 ...

  3. 深入理解Java虚拟机(四)Eden、Survivor、老年代、GC日志

    1. 年轻代 1.1 Eden区和Survivor区 新生代GC(Minor GC):指发生在新生代的垃圾收集动作,Minor GC非常频繁,新生代采用复制算法,一般回收速度也比较快.因为采用复制算法 ...

  4. 04.Java 堆内存 新生代 老年代?

    Java 中的堆是 JVM所管理的最大的一块内存空间,主要用于存放各种类的实例对象. 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young ).老年代 ( Old ).新生代 ( You ...

  5. Java虚拟机JVM的内存管理

    Java虚拟机JVM的内存管理 关键词 一.JVM整体架构 根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法区.程序计数器.本地方法栈五个部分. 名称 作用 特征 配置参数 异常 程序计数器 ...

  6. [JVM] java虚拟机 堆

    1.概念 Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共享的一块内存区域,在虚拟机启动时创建.此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存. J ...

  7. Spark 内存管理堆内和堆外内存规划_大数据培训

    堆内和堆外内存规划 作为一个 JVM 进程,Executor 的内存管理建立在 JVM 的内存管理之上,Spark 对 JVM 的堆内(On-heap)空间进行了更为详细的分配,以充分利用内存.同时, ...

  8. 深入理解Java虚拟机:jvm内存模型jdk1.8

    深入理解Java虚拟机:jvm内存模型jdk1.8 一.程序计数器 使用PC寄存器存储字节码指令地址有什么作用?为什么使PC寄存器记录当前线程的执行地址? PC寄存器为什么会被设定为线程私有? 二.J ...

  9. java新生代 老年代比例_JVM老年代和新生代的比例

    在 Java 中,堆被划分成两个不同的区域:新生代 ( Young ).老年代 ( Old ).新生代 ( Young ) 又被划分为三个区域:Eden.From Survivor.To Surviv ...

最新文章

  1. mysql连接命令行,从命令行连接到MySQL
  2. UI设计中,文本底部添加下换线
  3. dmg镜像如何写入u盘_最全macOS官方全家桶原版系统镜像
  4. java 修饰词_Java线程和Java修饰词
  5. Linux多线程编程-线程间参数传递
  6. IIS的ISAPI接口
  7. 班主任直接把奖学金名额给了我?就因为我用Python给她写了一个自动阅卷脚本
  8. kindeditor导入word文档 kindeditor word导入插件
  9. matlab求合同矩阵,matlab-线性代数 判断 合同矩阵
  10. android高德地图自定义地图,(android地图开发) 高德地图自定义对话框
  11. 大话信号与系统 --- 奇文共欣赏
  12. 西门子PLC S7-1200如何实现远程上下载?
  13. 滑动到尽头时去掉阴影效果
  14. 中职一年级计算机学情分析,学情分析
  15. python+selenium牛刀小试之自动化模拟网站广告点击
  16. Word加载EndNote插件
  17. 使用 Morphia 和 MongoDB 实现持久化
  18. 关于风机滑环的寿命以及工作原理
  19. 计算机二级java软件netBean安装(路径错误问题)
  20. webstorm解决git冲突

热门文章

  1. NRF24L01发送接收调试记录
  2. linux mtime参数,linux find mtime参数详解
  3. 在centos上安装html,Centos-7安装pdf2htmlEX
  4. 数组转集合集合转数组 split方法
  5. seo自动工具_【SEO工具】搭建一个网站需要用到哪些SEO工具?
  6. 小帅小胖智能机器人价格_小胖机器人CEO魏然:机器人+教育,是未来教育大势所趋...
  7. 不能使用泛型的形参创建对象_数据类型之----泛型
  8. idea2020.3升级lombok不能使用
  9. Spring Boot之发送HTTP请求(RestTemplate详解)
  10. 基于 Jenkins + JaCoCo 实现功能测试代码覆盖率统计