《JVM第7课》堆区

1.概念

堆是JVM中最重要的一块区域,JVM规范中规定所有的对象和数组都应该存放在堆中,在执行字节码指令时,会把创建的对象存入堆中,对象的引用地址存入虚拟机栈的栈帧中。不过当方法执行完之后,刚刚所创建的对象并不会立马被回收,也就是说对象并不会随着栈帧的消失而消失,而是要等JVM后台执行GC后,对象才会被回收。

2.指定堆大小

-Xms:指定堆的初始内存大小,ms(memory start)。等价于 -XX:InitialHeapSize;

-Xmx:指定堆的最大内存大小,mx(memory max)。等价于 -XX:MaxHeapSize;

一般会把 -Xms 和 -Xmx 设置为一样,这样JVM就不需要在GC后去修改堆的内存大小了,提高了效率。默认情况下,-Xms等于物理内存大小/64,-Xmx等于物理内存大小/4。

3.新生代和老年代

垃圾回收算法有很多,但基本上都会把内存分为新生代和老年代两块区域。新生代存放新创建的对象,老年代存放执行了许多次GC(默认为15次)后还存活的对象。

可以通过 -XX:NewRatio 参数来配置老年代和新生代的比例,默认为 -XX:NewRatio=2,表示新生代占1,老年代占2。一般是不需要调整的,只有明确知道存活时间比较长的对象偏多或偏少,才需要调整 -XX:NewRatio 的比值。

3.1 新生代

新生代又可以分为 Eden(伊甸园区)和 S0、S1 区。

Eden: 伊甸园区,新对象都会先放到Eden区。

S0、S1区: Survivor0、Survivor1区,也可以叫做from、to区,用来存放MinorGC(YGC)后存在的对象。

默认情况下 Eden、S0、S1 的比例为 8:1:1,也就是说Eden区占新生代大小的 8/10。可以通过 -XX:SurvivorRatio 来调整。

3.2 老年代

老年代存放执行了许多次GC后还存活的对象。老年代默认占内存区域的2/3。

3.3 动画演示

动画演示对象在内存各区域中的流转过程

  1. 对象会先被放到Eden区。
  2. 执行 Young GC 后会被放到S0或S1区,S0和S1不能同时非空,对象会在S0和S1之间反复跳跃。
  3. 在执行一定次数(默认为15次)的 Young GC 后假设对象还没有被回收掉,就会进入老年代区域。
  4. 如果新对象大小超过了 Eden 区剩余空间大小,则会直接进入S0或S1,如果S0或S1放不下则会直接进入老年代。
  5. 老年代继续执行 Old GC 对其中对象进行回收。
  6. 这里的 Young GC 和 Old GC 也可叫做 Minor GC 和 Major GC,它们并不是垃圾回收器的名字,只是代表年轻代和老年代的垃圾回过程

4.分代收集理念

上面的新生代老年代就是分代收集理念,有些时候会被叫做分代收集算法,但其实它是一种理念。默认几乎所有的垃圾回收算法都是采用分代收集理念。

为什么垃圾回收算法要把内存区域分为新生代和老年代,新生代里又包含Eden区、Survivor0、Survivor1区呢?

这是因为不同的对象存活时长是不一样的,所以要针对存活时长不同的对象采取不同的垃圾回收算法。

  • 新生代中的对象存活时间比较短,那么就可以采取"复制算法"(后面的章节会介绍)。
  • 老年代中的对象存活时间比较长,所以不太适合用复制算法,可以用"标记-清除算法"或"标记-整理算法"(后面的章节会介绍)。
相关推荐
lihao lihao1 小时前
linux线程
java·开发语言·jvm
南极企鹅17 小时前
JVM-编译执行过程
jvm
苏克贝塔21 小时前
.NET开发之.net framework对比.net core
jvm
cfm_29141 天前
JVM垃圾收集算法与收集器深度解析
jvm·测试工具·算法·性能优化
自律懒人1 天前
AI Agent 工作流编排实战:从单 Agent 到多 Agent,手搭一套能跑通的协作系统
jvm
石一峰6991 天前
SQLite 与 db_manager 集成关键概念详解
jvm·数据库·sqlite
布朗克1682 天前
34 JVM深入理解
java·jvm
eggrall2 天前
Linux线程:并发编程的双刃剑
jvm
程序员晨曦2 天前
深入浅出JVM内存结构
jvm·面试·职场和发展
cfm_29142 天前
JVM对象创建与内存分配机制深度解析
jvm