java老年_JVM内存中的年轻代,老年代

引言

对于大多数Java应用来说,Java Heap(Java堆)是JVM管理的内存中较大的一块,而且Java Heap是被所有线程共享的一块内存区域,于虚拟机启动时创建。

而Java堆的唯一目的就是存放对象实例。

由于Java堆是垃圾收集器管理的主要区域,因此也被称为”GC堆”。

再从内存回收的角度来看,由于现代收集器基本都采用分代收集算法,所以Java Heap还可以被细分为:

新生代和老年代,新生代再分得细致一点就可以分为Eden空间和两个相同大小相同的Survivor空间,下面来谈谈新生代和老年代。

新生代

12ca2f0a0f234b9cd2a403603106d571.png

通俗理解就是新创建的对象就是先进入新生代,然后创建久而且还未被回收的对象自然而然就进入老年代。

上面说了,年轻代又分为一个Eden空间和两个Survivor空间,这样分的意义是什么呢,这里不得不说一下一个垃圾收集算法:

复制算法:

这里不得不又介绍一下

传统的标记清除算法:就是首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

该算法有如下缺点:

1.效率问题

2.空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前出发另一次垃圾收集动作。

63ba8d9ed1d97427f2b2a3eec91ffdd4.png(图是截书上的,应该看得清吧)

所以复制算法就是主要为了解决以上的缺点,复制算法就是将可用内存按容量划分为大小相等两块,每次只使用其中的一块,

当这一块的内存用完了,就将还存活着的对象复制道另外一块上面,然后再把已使用过的内存空间一次清理掉,这样每次都是对整个半区进行内存回收,所以内存分配时也就不用去考虑内存碎片等复杂情况了,但是这种算法也有一个很明显的缺点,会缩小实际可以使用的内存,这里就直接缩小了一半!

79b0dfda10de0b9bf4999d026c9d5457.png

而其实年轻代这样分配Eden和两个两个Survivor其实就是采用了复制算法的思想,不过这就没有每次都只使用一次这么夸张,这里年轻代每次都只使用Eden和一个Survivor,即新创建的对象都放入Eden和一个Survivor,如果内存不够,就会先把这两个空间上还存活的对象放入另一个Survivor空间,然后进行Minor GC。

而新生代为什么要采用这种算法呢,这是因为新生代的对象大部分都是“朝生夕死”,因此这里虽然采用了复制算法的思想,但是并不需要按1:1来划分空间,而只需要分配一小部分空间给Survivor即可,HotSpot虚拟机默认Eden和Survivor比例是8:1 ,即每次新生代可用内存空间为90%,当然如果在这种情况下由超过10%的对象存活(因为这里一个Survivor空间只有10%),即进行过一次Minor GC之后,一个Survivor空间装不下存活的对象,这就需要老年代进行分配担保了。

设置新生代空间:

1.直接对新生代大小进行设置  -Xmn   例如:-Xmn10M   新生代大小为10M(eden+ 2 survivor space)

2.通过设置老年代与新生代的比例来设定  -XX:NewRatio 例如:-XX:NewRatio=4

(表示年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5,Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置)

设置Eden与Survivor的比例:-XX:SurvivorRatio 例如:-XX:SurvivorRatio=8

(则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10)

老年代

上面说过经过Minor GC之后,如果Survivor存放不下存活的对象,对象就会通过分配担保机制进入老年代,而如果老年代空间还不够,就会进行Full GC。

老年代使用的回收算法是标记整理算法:

该算法也有标记过程,和标记清除算法一样,但是后面不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存:

3ea21d6bda42d1ffe6df27ee476194bb.png

进入老年代除了以上那种情况还有以下情况:

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

大对象是需要大量连续内存空间的Java对象,最典型的大对象就是那种很长的字符串以及数组,

经常出现大对象容易导致内存还有不少空间时就提前出发垃圾收集以获取足够的连续空间来安置它们。

虚拟机提供了 -XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配,

目的是避免在Eden区以及两个Survivor区之间发生大量的内存赋值(新生代采用复制算法收集内存)

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

虚拟机给每个对象定义了一个对象年龄计数器,如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动道Survivor空间,并且对象年龄设为1,并且每经过一次Minor GC,就会多一岁,当达到一定值时,就会被移动道老年代(默认为15),可以通过设置-XX:MaxTenuringThreshold设置。

3.动态对象年龄绑定

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值