实战:内存分配与回收策略
2021/12/24 7:11:04
本文主要是介绍实战:内存分配与回收策略,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1对象优先在Eden分配
大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC
参数:
-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
表示Java堆20MB,10MB新生代,10MB老年代,新生代中一个Eden与一个Survivor大小比8:1
代码:
public class JvmTest { private static final int _1MB = 1024*1024; public static void main(String[] args) { // TODO Auto-generated method stub byte[] allocation1,allocation2,allocation3,allocation4; allocation1 = new byte[2* _1MB]; allocation2 = new byte[2* _1MB]; allocation3 = new byte[2* _1MB]; allocation4 = new byte[4* _1MB]; //出现一次MinorGC } }
在分配allocation4时,Eden已经被占用6MB,剩余不够4MB,因此发生minor gc,并且三个2MB大小的对象全部无法放入1MB大小的Survior区,所以只能通过分配担保机制提前转移到老年代去。
结果
Heap PSYoungGen total 9216K, used 7291K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000) eden space 8192K, 89% used [0x00000000ff600000,0x00000000ffd1efe8,0x00000000ffe00000) from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000) to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000) ParOldGen total 10240K, used 4096K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000) object space 10240K, 40% used [0x00000000fec00000,0x00000000ff000010,0x00000000ff600000) Metaspace used 2624K, capacity 4486K, committed 4864K, reserved 1056768K class space used 279K, capacity 386K, committed 512K, reserved 1048576K
这里与书中不同,我的垃圾收集器只将两个2MB对象放入OldGen
2 大对象直接进入老年代
在Java虚拟机中要避免大对象的原因是,在分配空间时,他容易导致内存明明还有不少空间时就提前触发垃圾收集。而当复制对象时,大对象需要高额的复制开销。
参数
-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:PretenureSizeThreshold=3145728
表示大于3MB的对象会被直接放入老年代(不过只对Serial和ParNew有效)
代码
public class JvmTest { private static final int _1MB = 1024*1024; public static void main(String[] args) { // TODO Auto-generated method stub byte[] allocation4 = new byte[4* _1MB]; //出现一次MinorGC } }
3长期存活的对象将进入老年代
参数
-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=1 -XX:+PrintTenuringDistribution
表示年龄到达1变为老年代
-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:+PrintTenuringDistribution
表示年龄到达15变为老年代
代码
public class JvmTest { private static final int _1MB = 1024*1024; public static void main(String[] args) { // TODO Auto-generated method stub byte[] allocation1,allocation2,allocation3; //出现一次MinorGC allocation1 = new byte[_1MB / 4]; allocation2 = new byte[_1MB * 4]; allocation3 = new byte[_1MB * 4]; allocation3 = null; allocation3 = new byte[_1MB * 4]; } }
不过我的结果两种一致,估计是因为参数不适用于我当前的收集器
4动态对象年龄判定
参数与上面的值为15的一致,allocation1和2加起来是512kb,大于survivor的一半,被视为老年代。
public class JvmTest { private static final int _1MB = 1024*1024; public static void main(String[] args) { // TODO Auto-generated method stub byte[] allocation1,allocation2,allocation3,allocation4; //出现一次MinorGC allocation1 = new byte[_1MB / 4]; allocation2 = new byte[_1MB / 4]; allocation3 = new byte[_1MB * 4]; allocation4 = new byte[_1MB * 4]; allocation4 = null; allocation4 = new byte[_1MB * 4]; } }
5 空间分配担保
在老年代最大可用连续空间小于历次晋升到老年代对象的平均大小,也就是有风险的Minor GC
这个时候如果失败会进行Full GC,因此,此时设置HandlePromotionFailure其实就是为了避免Full GC过于频繁。
在JDK 6之后,规则变为,在老年代最大可用连续空间小于历次晋升到老年代对象的平均大小,就进行Full GC,不用设置。
参数
-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:-HandlePromotionFailure
代码
public class JvmTest { private static final int _1MB = 1024*1024; public static void main(String[] args) { // TODO Auto-generated method stub byte[] allocation1,allocation2,allocation3,allocation4; byte[] allocation5,allocation6,allocation7; allocation1 = new byte[_1MB * 2]; allocation2 = new byte[_1MB * 2]; allocation3 = new byte[_1MB * 2]; allocation1 = null; allocation4 = new byte[_1MB * 2]; allocation5 = new byte[_1MB * 2]; allocation6 = new byte[_1MB * 2]; allocation4 = null; allocation5 = null; allocation6 = null; allocation7 = new byte[_1MB * 2]; } }
在我的电脑上运行失败,无法识别HandlePromotionFailure
这篇关于实战:内存分配与回收策略的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-26结对编程到底难不难?答案在这里
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现
- 2024-06-03为什么以及如何要进行架构设计权衡?
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)
- 2024-05-31全网首发!软考2024年5月《软件设计师》真题+解析+答案!(21-30题)