了解内存分配以及垃圾收集器

内存分配

在类加载检查之后,JVM虚拟机将会为新生对象分配内存。在为对象划分内存的时候可能出现两个问题:

1.如何划分内存

2.在并发条件下,可能存在在给对象A分配内存的时候,指针还没来得及修改,对象B又使用了原来的指针来划分内存。

划分内存的方式我已知的有两种①指针碰撞(用过的内存放一边,没用的内存放另外一边中间用一个指针隔开)②空闲列表(使用的和未使用的内存交错放置,虚拟机会维护一张表用来记录哪些内存可用,哪些内存还未用)

我们都知道大部分对象首先会被分配到eden区,当Eden区满的时候就会触发minor gc,那时只有少量的对象存活下来挪到survivor区,当下一次eden区被塞满时,minor gc会将eden区和非空的survivor区的垃圾对象回收,并将剩余的非垃圾对象移到另外一个survivor区。当这些对象反复挪动15次(一般是15次,可以自己调)就会被移入老年代。有些人认为对象必须经过15次的挪动才能进入老年代,其实并不是的

那么哪些情况对象会直接进入老年代呢?

①大对象直接进入老年代:-XX:PretenureSizeThreshold 参数可以设置大对象的大小,如果对象超过设置的大小那么就会直接进入老年代
②长期存活的对象进入老年代:对象在经过一次minor gc后且被survivor区接收,那么这些对象的年龄就会+1,当这些对象的年龄达到15岁的时候才会进入老年代(不同的垃圾收集器默认年龄不同),也可以通过-XX:MaxTenuringThreshold参数来设置
③动态年龄判断:当一批对象的总大小大于survivor区的50%时,会将年龄1+年龄2+年龄n这个对象中年龄n以上的对象放入老年代中,这么做是为了让那些长久存活的对象尽快进入老年代中。
④老年代空间分配担保机制:minor gc触发之前虚拟机都会计算老年代的剩余可用内存,如果这个内存小于年轻代理现在所有对象的大小之和,那么会触发full gc,如full gc结束之后还是没有空间存放minor gc之后存活的对象则会发生“OOM”。

垃圾收集算法以及垃圾收集器

垃圾收集算法

1.标记-复制算法
为了解决效率问题,复制算法会将内存分为两份,每次使用其中的一份,但那一份内存被用完之后,会将存活的对象复制到另外一份中,并将原来那一份清空。但有着明显的缺点,浪费内存。

2.标记-清除算法
标记存活的对象,回收未被标记的对象,但也有着明显的缺点:若标记的对象太多,效率不高;标记清除后也会产生大量不连续的碎片

3.标记-整理算法
和标记-清除算法类似,但会将标记的对象整理到一端,清除端边界以外的内存。

垃圾收集器

1.Serial收集器
串行收集器是最基本的垃圾收集器。它是一个单线程的收集器。它的单线程不仅体现在 只使用一条线程去收集垃圾,也在当它执行垃圾收集工作时会触发长时间的STW,直到它收集完成。影响用户体验。

2.Parallel Scavenge收集器
在Serial收集器的基础上开发的多线程版本,默认线程数与CPU核数相同。

3.ParNew收集器
跟Parallel收集器类型,区别是它一般跟CMS收集器配合使用。 

 

4.CMS收集器
该收集器是一种以获取最短的停顿时间未目标的收集器。非常注重用户体验,是虚拟机第一款真正意义上的并发收集器,第一次实现了让垃圾收集线程和用户线程同时工作的状态。
CMS收集过程是比较复制的,整个过程主要分为5个:
①初始标记:暂停其他线程,记录gc roots能直接引用的对象(速度很快)
②并发标记:从gc roots开始遍历整个对象图,这个过程耗时较长但不需要停顿用户线程。但也由于用户线程的继续运行,可能会导致已经标记过的对象状态发生改变。
③重新标记:修正并发标记过程中状态发生改变的标记对象,这个阶段会触发STW时间,且时间比初始标记要长。
④并发清理:开启用户线程,同时GC线程会对未标记的区域做清扫。
⑤并发重置:重置本次GC过程中的标记数据。
 

优点:并发收集,低停顿

缺点:对CPU资源敏感,无法处理浮动垃圾(在并发标记和并发清理过程中产生吃垃圾), 会产生大量的空间碎片。

5.G1收集器
这是一款面向服务器的收集器,主要面对具有大容量内存的机器,以极高的概率满足低停顿高吞吐量的性能特征。
G1收集器不再简单的将堆分为eden,survivor,old区,而是将整个堆划分为多个大小相等的独立区域(Regin,最多可以有2048个)。

G1虽然保留了年轻代和老年代的概念,但已经不是物理隔阂了,它们都是Regin的集合。同事G1也引入了一个新的区Humongous区,专门去存放打的对象。在G1中,大对象的判断依据是一个对象超过了一个Regin区的50%,那么那个对象就是个大对象,可以存入Humongous区,若一个Humongous区放不下,可以横跨多个Regin存放。当然当触发full gc时也会将Humongous区回收。
G1收集器的运行大概分为下面几个过程:
①初始标记:跟CMS类似
②并发标记:同CMS类似
③最终标记:同CMS的重新标记
④筛选回收:这阶段会对各个Regin的回收价值和成本进行排序,根据用户所期望的停顿时间制定回收计划。

什么场景合适使用G1
a.50%以上的堆被存活对象占用
b.对象分配和晋升的熟读变化非常大
c.垃圾回收时间特别长(超过1s)
d.8GB以上的堆内存
e.停顿时间要求在500ms以内

6. ZGC收集器
是一款JDK11新加入的具有实验性质的低延迟垃圾收集器。ZGC的目标主要有四个:

①支持TB量级的堆
②最大GC停顿时间不超过10ms
③奠定未来GC特性的基础
④最糟糕的情况下吞吐量会降低15%

在ZGC中是没有分代的概念,ZGC也是基于Regin内存分布的,但它将Regin分为大,中,小三类容量:
①小型Regin:容量固定为2M,用于放置小于256KB的小对象
②中型Regin:容量固定为32M,用于放置大于等于256KB但小于4M的对象
③大新Regin:容量不固定可以动态变化,但必须是2M的整数倍,用于放置4M以上的对象。 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值