对象如何进入老年代的问题

现代虚拟机一般使用的内存回收策略是分代收集,即把对象分为两代,新生代使用复制算法回收内存,老年代使用标志-整理算方法回收内存。但是有时候新生代对象存活率较高,导致有大对象分配时内存不足,虚拟机也会采用担保机制是大对象进入老年代。

什么时候发生内存回收

大多数情况下,对象在新生代Eden区分配,当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC。同理,当老年代没有足够的空间时也会发起一次Full GC/Major GC

内存担保机制

现代虚拟机把新生代分为三个区域,一个Eden区域,两个Survivor区域,Eden区域与Survivor区域的比例大小是8:1,虚拟机在Minor GC时在新生代采用复制算法,将存活对象复制到一个Survivor上面,如果Survivor空间不够用时,就需要老年代进行分配担保。
在发生Minor GC之前虚拟机会先检查老年代最大可用的连续空间是否大于新生代对象的总空间。如果这个条件成立,那么Minor GC可以确保是安全的。如果不成立,虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。如果允许,虚拟机会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代的平均年龄(因为事先不知道存活对象的内存空间,所以取了平均值)。若果大于,虚拟机会尝试进行一次Minor GC,但是这次Minor GC存在风险。如果小于,或者HandlePromotionFailure不允许担保,那这次也要改为Full GC

大对象直接进入老年代

大对象是指需要大量连续内存空间的对象,例如很长的字符串以及数组。
虚拟机设置了一个-XX:PretenureSizeThreshold参数,令大于这个设置的对象直接在老年代分配。目的就是为了防止大对象在Eden空间和Survivor空间来回大量复制。

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

虚拟机给每个对象定义了一个对象年龄(Age)计数器,如果对象在Eden区出生并经过第一次Mintor GC后仍然存活,并且能被Survivor接纳,并被移动到Survivor空间上,那么该对象年龄将被设置为1。对象在Survivor区中每熬过一次Minor GC,年龄就加一,当他的年龄增加到一定程度,就会被移动到老年代(年龄值默认为15)。对象晋升老年代的阈值可以通过-XX:MaxTenuringThreshold设置。

动态年龄判断并进入老年代

为了更好的适应不同程序的内存状况,虚拟机并不是永远要求对象的年龄必须达到MaxTenuringThreshold才会晋升到老年代。如果在Survivor空间中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无需达到MaxTensuringThreshold的要求年龄。

原文地址:https://www.cnblogs.com/curiousforcode/p/12072444.html

时间: 2024-10-07 14:35:52

对象如何进入老年代的问题的相关文章

java中什么样的对象能够进入老年代

1.大对象:所谓的大对象是指需要大量连续内存空间的java对象,最典型的大对象就是那种很长的字符串以及数组,大对象对虚拟机的内存分配就是坏消息,尤其是一些朝生夕灭的短命大对象,写程序时应避免. 2.长期存活的对象:虚拟机给每个对象定义了一个对象年龄(Age)计数器,如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并且对象年龄设为1,.对象在Survivor区中每熬过一次Minor GC,年龄就增加1,当他的年龄增加

GC新生代对象晋升到老年代情况总结

对象优先在Eden分配,且新生代对象晋升到老年代有多种情况, 现在做一个总结: (1).Eden区满时,进行Minor GC,当Eden和一个Survivor区中依然存活的对象无法放入到Survivor中,则通过分配担保机制提前转移到老年代中. (2).若对象体积太大, 新生代无法容纳这个对象,-XX:PretenureSizeThreshold即对象的大小大于此值, 就会绕过新生代, 直接在老年代分配, 此参数只对Serial及ParNew两款收集器有效. (3).长期存活的对象将进入老年代.

GC 老年代 新生代

参考资料: http://blog.csdn.net/flamezyg/article/details/44673951 http://www.blogjava.net/ldwblog/archive/2013/07/24/401919.html http://www.360doc.com/content/12/1023/16/9615799_243296263.shtml   JVM中的堆,一般分为三大部分:新生代.老年代.永久代: 一:新生代:主要是用来存放新生的对象.一般占据堆的1/3空间

【转】Java中的新生代、老年代、永久代和各种GC

JVM中的堆,一般分为三大部分:新生代.老年代.永久代: 1 新生代 主要是用来存放新生的对象.一般占据堆的1/3空间.由于频繁创建对象,所以新生代会频繁触发MinorGC进行垃圾回收. 新生代又分为 Eden区.ServivorFrom.ServivorTo三个区. Eden区:Java新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代).当Eden区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收. ServivorTo:保留了一次MinorGC过程中的幸存者.

新生代和老年代垃圾回收的细节

新生代和老年代 对象在被实例化之后,都是属于新生代. 大部分新生代的生命周期都是及其短暂的,例如在一个方法中创建的对象会随着方法执行完毕,栈空间的栈帧出栈后而失去引用. 而有一些对象确实会长期存活在堆内存的,比如被Static引用的对象.这种对象不会轻易的被垃圾回收器回收. 所以JVM会将堆内存分为两个区域,一个年轻代,一个老年代. 其中年轻代,顾名思义,就是创建和使用完之后立马就要被回收的对象放在里面.然后老年带呢,就是把一些会长期存活的对象放在里面. 为什么要分成新生代和老年代 很多人都会有

Java GC、新生代、老年代

堆内存 Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象.在 Java 中,堆被划分成两个不同的区域:新生代 ( Young ).老年代 ( Old ).新生代 ( Young ) 又被划分为三个区域:Eden.From Survivor.To Survivor.这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收.堆的内存模型大致为: 从图中可以看出: 堆大小 = 新生代 + 老年代.其中,堆的大小可以通过参数 –Xms.-X

堆中的新生代与老年代

1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描.而我们的很多对象都是朝生夕死的,如果分代的话,我们把新创建的对象放到某一地方,当GC的时候先把这块存"朝生夕死"对象的区域进行回收,这样就会腾出很大的空间出来. 2.年轻代中的GC     HotSpot JVM把年轻代分为了三部分:1

jvm中的年轻代 老年代 持久代 gc

虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Generation)和持久代(Permanent Generation).其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大.年轻代和年老代的划分是对垃圾收集影响比较大的. 年轻代: 所有新生成的对象首先都是放在年轻代的.年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象.年轻代分三个区.一个Eden区,两个Survivor区(一般而言).大部分对象在Eden区中生成.当Ed

[Java] 新生代和老年代垃圾回收策略

一.新生代:采用复制策略 Eden块,连个survival块 回收的时候,将Eden和当前使用的survival块当中的存活的对象转移到另一块survival当中,清空Eden和当前使用的survival块. 二 .老年代:标记移动算法 由于变化不是很大,而且大部分都是长期活着的对象或者大对象,所以使用新生代中的survival块无法全部容纳.这里使用标记移动的策略. [1] http://www.admin10000.com/document/1671.html