Java虚拟机:内存分配与回收策略

1.对象优先在Eden分配

=================

大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC。

例子1:

Serial + Serial Old(UseSerialGC) 或者 ParNew + Serial Old(UseParNewGC)

GC环境:垃圾收集器为Serial + Serial Old(ParNew + Serial Old),年轻代大小为100M,Eden:Survivor = 8 :1,所以Eden为80M,两个Survivor各10M,老年代为100M。

GC分析:当要分配allocation5时,Eden空间不足,进行Minor GC,此时年轻代空间从76595K降低到698K。这是由于allocation1、allocation2、allocation3、allocation4对象的大小皆超过Survivor空间大小(10M),因此allocation1、allocation2、allocation3、allocation4对象皆通过分配担保机制提前转移到老年代,年轻代剩余的698k为JVM的内部对象,进行Minor GC后进入了Survivor区。

例子2:

Parallel Scavenge + Parallel Old

GC环境:垃圾收集器为Parallel Scavenge + Parallel Old,年轻代大小为100M,Eden:Survivor = 8 :1,所以Eden为80M,两个Survivor各10M,老年代为100M。

GC分析:当要分配allocation5时,Eden空间不足,进行Minor GC,此时年轻代空间从76595K降低到888k。这是由于allocation1、allocation2、allocation3、allocation4对象的大小皆超过Survivor空间大小(10M),因此allocation1、allocation2、allocation3、allocation4对象皆通过分配担保机制提前转移到老年代,年轻代剩余的888k为JVM的内部对象,进行Minor GC后进入了Survivor区。后面的Full GC会在后面的空间分配担保进行讲解。

例子3:

Parallel Scavenge + Parallel Old

GC环境:垃圾收集器为Parallel Scavenge + Parallel Old,年轻代大小为100M,Eden:Survivor = 8 :1,所以Eden为80M,两个Survivor各10M,老年代为100M。

GC分析:该例子跟例子2的区别是把例子2的最后两次分配10M和30M合并成了1次分配40M,结果没有进行GC,原因是在Parallel Scavenge收集器下:将要分配的对象大小 >= Eden总空间的一半,对象通过分配担保机制直接进入老年代,否则尝试进行MinorGC。

2.大对象直接进入老年代

================

所谓的大对象是指,需要大量连续内存空间的Java对象,最典型的大对象就是那种很长的字符串以及数组(例子中的byte[]数组就是典型的大对象)。

虚拟机提供了一个-XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配。只对Serial和ParNew两款收集器有效,Parallel Scavenge收集器不认识这个参数,Parallel Scavenge收集器一般并不需要设置。

例子1:没设置PretenureSizeThreshold

GC分析:可以看出老年代为空,allocation对象正常进入新生代。

例子2:设置PretenureSizeThreshold=3145728

GC分析:可以看出老年代被占用了4M,allocation对象由于超过PretenureSizeThreshold设置的3M(3145728 = 3 * 1024 * 1024),被认为是大对象直接进入老年代。

3.长期存活的对象将进入老年代

===================

如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并且对象年龄设为1。对象在Survivor区中每“熬过”一次Minor GC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15岁),就将会被晋升到老年代中。对象晋升老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshold设置。

例子1:不设置MaxTenuringThreshol参数

GC环境:垃圾收集器为Serial + Serial Old(ParNew + Serial Old),年轻代大小为100M,Eden:Survivor = 8 :1,所以Eden为80M,两个Survivor各10M,老年代为100M。

GC分析:没设置MaxTenuringThreshold时,MaxTenuringThreshold的默认值为15,必须经过15次Minor GC才能晋升到老年代,因此经过该例子经过两次Minor GC后,年轻代仍有3257k,即allocation1对象的仍在Survivor区。

例子2:设置参数MaxTenuringThreshold=1

GC分析:该例子跟上面差别只有一个,将MaxTenuringThreshold设为1,可以看出第二次Minor GC时,年轻代已经被清空,allocation1对象因为年龄符合MaxTenuringThreshold设置的值,因此进入老年代。

4.动态对象年龄判断

==============

如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。

例子1:allocation1+allocation2大于Survivor空间一半

最后

既已说到spring cloud alibaba,那对于整个微服务架构,如果想要进一步地向上提升自己,到底应该掌握哪些核心技能呢?

就个人而言,对于整个微服务架构,像RPC、Dubbo、Spring Boot、Spring Cloud Alibaba、Docker、kubernetes、Spring Cloud Netflix、Service Mesh等这些都是最最核心的知识,架构师必经之路!下图,是自绘的微服务架构路线体系大纲,如果有还不知道自己该掌握些啥技术的朋友,可根据小编手绘的大纲进行一个参考。

image

如果觉得图片不够清晰,也可来找小编分享原件的xmind文档!

且除此份微服务体系大纲外,我也有整理与其每个专题核心知识点对应的最强学习笔记:

  • 出神入化——SpringCloudAlibaba.pdf

  • SpringCloud微服务架构笔记(一).pdf

  • SpringCloud微服务架构笔记(二).pdf

  • SpringCloud微服务架构笔记(三).pdf

  • SpringCloud微服务架构笔记(四).pdf

  • Dubbo框架RPC实现原理.pdf

  • Dubbo最新全面深度解读.pdf

  • Spring Boot学习教程.pdf

  • SpringBoo核心宝典.pdf

  • 第一本Docker书-完整版.pdf

  • 使用SpringCloud和Docker实战微服务.pdf

  • K8S(kubernetes)学习指南.pdf

image

另外,如果不知道从何下手开始学习呢,小编这边也有对每个微服务的核心知识点手绘了其对应的知识架构体系大纲,不过全是导出的xmind文件,全部的源文件也都在此!

image

  • K8S(kubernetes)学习指南.pdf

[外链图片转存中…(img-JU6djxkE-1714390869029)]

另外,如果不知道从何下手开始学习呢,小编这边也有对每个微服务的核心知识点手绘了其对应的知识架构体系大纲,不过全是导出的xmind文件,全部的源文件也都在此!

[外链图片转存中…(img-3bMPX6CN-1714390869029)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 24
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值