JVM的Enen区和Survivor区

本文详细介绍了JVM堆分代的概念,重点讲述了年轻代的工作原理,包括新生代GC过程及对象生命周期,同时还提供了年轻代的一些关键JVM参数配置。

1.JVM堆分代(新生代,老年代,永久代)
JVM分代图

2.新生代GC
我们先来捋一捋,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能。你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描。而我们的很多对象都是朝生夕死的,如果分代的话,我们把新创建的对象放到某一地方,当GC的时候先把这块存“朝生夕死”对象的区域进行回收,这样就会腾出很大的空间出来。
在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。

3.一个对象的这一辈子
我是一个普通的java对象,我出生在Eden区,在Eden区我还看到和我长的很像的小兄弟,我们在Eden区中玩了挺长时间。有一天Eden区中的人实在是太多了,我就被迫去了Survivor区的“From”区,自从去了Survivor区,我就开始漂了,有时候在Survivor的“From”区,有时候在Survivor的“To”区,居无定所。直到我18岁的时候,爸爸说我成人了,该去社会上闯闯了。于是我就去了年老代那边,年老代里,人很多,并且年龄都挺大的,我在这里也认识了很多人。在年老代里,我生活了20年(每次GC加一岁),然后被回收。

4.有关年轻代的JVM参数

1)-XX:NewSize和-XX:MaxNewSize

用于设置年轻代的大小,建议设为整个堆大小的1/3或者1/4,两个值设为一样大。

2)-XX:SurvivorRatio

用于设置Eden和其中一个Survivor的比值,这个值也比较重要。

3)-XX:+PrintTenuringDistribution

这个参数用于显示每次Minor GC时Survivor区中各个年龄段的对象的大小。

4).-XX:InitialTenuringThreshol和-XX:MaxTenuringThreshold

用于设置晋升到老年代的对象年龄的最小值和最大值,每个对象在坚持过一次Minor GC之后,年龄就加1。

文章转自:转载自并发编程网 – ifeve.com本文链接地址: 聊聊JVM的年轻代

<think>嗯,用户问的是JVM中的fromto域的垃圾回收过程及对象流转机制。首先,我得回忆一下JVM的内存结构,尤其是堆内存的部分。堆内存通常分为新生代老年代,而新生代又分为Eden两个Survivor,也就是fromto。用户提到的fromto应该是指Survivor中的这两个域。 首先,我要确认垃圾回收的过程,特别是针对新生代的Minor GC。Minor GC发生时,Eden中存活的对象会被复制到其中一个Survivor,通常是to,而原本在from中的存活对象也会被复制到另一个Survivor,也就是to,同时年龄增加。每次GC后,fromto的角色会交换,这样下一次GC时,原来的to就变成了新的from。 接下来,对象在Survivor之间的流转机制。每次Minor GC后,存活对象的年龄会增加1岁,当年龄达到阈值(默认15)时,会被晋升到老年代。不过,JVM还有动态年龄判定的机制,如果某一年龄的对象总大小超过Survivor的一半,那么年龄大于等于该年龄的对象会被直接晋升到老年代,而不用等到15次。 需要解释清楚对象从Eden到Survivor,再到老年代的过程,以及fromto的角色转换。此外,可能需要提到为什么需要两个Survivor,这主要是为了解决内存碎片的问题,使用复制算法可以有效地整理内存,避免碎片化。 用户可能还关心触发GC的条件,比如Eden满时触发Minor GC,或者当调用System.gc()时建议Full GC,但实际触发与否由JVM决定。同时,引用提到的可达性分析算法GC Roots的概念,这些是判断对象存活的关键,不过用户的问题更侧重于对象在内存域的流转,这部分可能需要简要提及。 另外,用户提供的引用内容中提到方法的垃圾回收、System.gc()的影响以及动态年龄判定,这些可以作为补充信息。比如,动态年龄判定如何影响对象晋升到老年代,或者方法回收与堆内存回收的别。 需要注意用户可能存在的误,比如fromto是否固定不变,或者对象何时晋升到老年代。需要明确说明Survivor是每次GC后交换角色,以及晋升的条件除了年龄还有动态判定。 最后,整理回答的结构,先介绍Survivor的结构作用,然后详细描述垃圾回收的过程,包括对象的复制年龄增长,再解释对象晋升到老年代的机制,最后补充相关的优化策略如动态年龄判定,并引用提供的参考资料中的内容来支持解释。</think>### JVM Survivor(From/To)垃圾回收与对象流转机制 #### 一、Survivor的结构 JVM堆内存中的新生代(Young Generation)分为$Eden$两个$Survivor$(From/To),默认比例是$8:1:1$。对象初次分配时进入$Eden$,经历**Minor GC**后存活的对象会被转移到$Survivor$,通过**复制算法**实现内存整理与分代管理[^3]。 #### 二、垃圾回收过程 1. **初次分配** 新对象优先分配在$Eden$。当$Eden$空间不足时,触发**Minor GC**。 $$ \text{Minor GC触发条件:} \quad \text{Eden已满} $$ 2. **存活对象复制** - **第一次Minor GC**:$Eden$存活对象复制到$To$,同时清理$Eden$。 - **后续Minor GC**: - $Eden$$From$(原$To$)的存活对象统一复制到新的$To$ - 每次复制后,对象年龄$+1$ - **角色交换**:$From$$To$互换身份,为下次GC做准备 3. **对象晋升条件** - **年龄阈值**:默认$15$次(可通过`-XX:MaxTenuringThreshold`调整) - **动态年龄判定**:若某年龄对象总大小超过$Survivor$的一半,年龄$\geq$该值的对象直接晋升到老年代 #### 三、对象流转示意图 ``` Eden → (Minor GC) → To → (年龄增长/交换角色) → From → (再次Minor GC) → To或老年代 ``` #### 四、关键机制解析 1. **复制算法优势** - 避免内存碎片化 - 仅保留存活对象,回收效率高(空间换时间) 2. **可达性分析支持** 存活对象判定依赖**GC Roots**引用链(如虚拟机栈、方法静态属性等),未被引用的对象会被回收[^5]。 3. **与老年代交互** - **Major GC/Full GC**会清理老年代,但频繁调用`System.gc()`可能强制触发Full GC[^2][^4] - 大对象可能直接进入老年代(通过`-XX:PretenureSizeThreshold`参数控制) #### 五、优化策略 1. **调整Survivor比例**:根据对象存活率调整`-XX:SurvivorRatio` 2. **避免过早晋升**:监控对象年龄分布,调整`MaxTenuringThreshold` 3. **空间分配担保**:老年代需保留足够空间,否则触发Full GC ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值