内存分配策略
Java 内存自动管理可归结为自动化地解决了两个问题:给对象分配内存以及回收分配给对象的内存。
前言
一本好书,每读一遍都会有不同的感受。写读书笔记,一来是便于平时查阅,毕竟技术书籍都比较厚,不方便随时携带;二来是督促自己多读书,理论与实践结合才能不断提升自己。
【深入理解Java虚拟机】阅读笔记: 3.6 内存分配与回收策略
对象优先在 Eden 分配
这里通过 -XX:+UseSerialGC
参数指定使用 Serial / Serial Old收集器。
代码清单如下:
1 | private static final int _1MB = 1024 * 1024; |
运行结果:
1 | [GC[DefNew: 7143K->296K(9216K), 0.0067950 secs] 7143K->6440K(19456K), 0.0068310 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] |
执行代码中分配 allocation4 对象时发生了一次 Minor GC,新生代
7143K->296K,内存总占用量几乎未减少 7143K->6440K。已有的 3 个 2MB 大小的对象无法放入 Survivor 空间,通过分配担保机制提前转移到了老年代。
大对象直接进入老年代
代码清单如下:
1 | private static final int _1MB = 1024 * 1024; |
运行结果:
1 | Heap |
allocation 对象大小超过了 3MB,直接被分配在老年代中。
长期存活的对象进入老年代
代码清单如下:
1 | private static final int _1MB = 1024 * 1024; |
运行结果:
1 | [GC[DefNew |
可以看到 allocation1 在第二次 GC 时进入老年代,Survivor 占用变成 0KB
动态对象年龄判定
如果在 Survivor 空间中相同年龄所有对象大小的总和大于 Survivor 空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到 MaxTenuringThreshold 中要求的年龄
空间分配担保
若老年代最大可用的连续空间大于新生代所有对象总空间,则 Minor GC 是安全的
否则,查看 HandlePromotionFailure 是否设置为允许担保失败
若允许,检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小
如果大于,尝试进行一次有风险的 Minor GC
如果小于,直接进行 Full GC
注:在 JDK 6 Update 24 之后,HandlePromotionFailure 参数不会影响虚拟机的空间分配担保策略,即按如下流程执行
参考
周志明. 深入理解Java虚拟机
- 2017-10-20
主要介绍常见垃圾收集算法的思想。
- 2017-10-22
如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。
- 2019-10-13
jstat
是 jdk 自带的一个命令行工具,用于监控 java 虚拟机的统计信息,通常可用它查看指定 java 进程的 gc 情况。 - 2017-10-15
Java 虚拟机所管理的内存包括多个运行时数据区域,每个区都有自己的特点。
- 2017-10-20
在堆里面存放着 Java 世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”。