2020-08-17

GC

哪些内存要回收

栈中的栈帧随着方法的进入顺序的执行的入栈和出战的操作,一个栈桢需要分配多少内存取决于具体的虚拟机实现并且在编译器间就确定下来,当方法或线程执行完毕后没存就随着回收。

方法区存放着类加载信息,但是一个接口中多个实现类需要的内存可能不太一样,一个方法中多个分支需要的内存可不一样,这部分内存的分布和回收都是动态的,GC关注的也正是这部分的内存。java堆是GC的重点目标,GC进行回收时就是确定哪些对象存货,哪些死去。

堆区的回收区域

为了高效 的回收,jvm将堆分为三个区

新生代:newSize和MaxNewSize分别控制初始大小和最大大小

老年代

永久代:1.8之后采用原空间。

GC为什么要分代

由于GC的整个工作过程中都要“Stop The World”,如果能想办法缩短GC一次工作的时间长度,让整个GC堆耗时变短,那不如只收集一部分,于是就有好几种不同的划分GC堆的方式来实现部分收集。

metaspace原空间

用来代替Perm永久区,希望内存的管理不再受到限制。不希望出现相关的OOM问题。有两大部分

  • Klass Metaspace:这块内存用来存klass运行时数据结构,可通过参数来控制,但是默认是1G
  • NoKlass Metaspace:用来存klass相关的其他内容,是由多块内存合起来的,在没有达到限制条件时会不断加长,保持持续工作。
判断对象是否存活

1.引用计数算法:给对象添加一个引用计数器,每次对象被引用,引用失效时就减1,当为0时就判断对象不会再被引用。

优点是实现简单效率高,被广泛使用,缺点是难以解决循环引用的问题,两个对象互相引用已经不会再被其他引用,导致一致不会为0无法进行回收。

2.可达性分析算法:可解决循环利用的问题,通过GC-Roots的对象为起点,搜索经过的路径称位引用链,当一个对象到GC-Roots没有任何引用跟他连接则证明对象不可用。即使可达性算法中不可达的对象,也不是一定要马上被回收,还有可能被抢救一下。

标记清除算法

分为标记和清除两部分,首先标记处所有需要回收的对象,在标记完成后统一回收所有被标记的对象。标记阶段就是可达性分析算法的过程,遍历所有的GCRoots对象,可达的对象都在header中打上标记,清除阶段是对堆内存进行遍历,如果发现某个对象没有被标记则将其回收。其过程必须停止所有java执行线程。效率不高,空间上会产生大量连续不断的内存碎片

复制算法

将可用内存按容量划分为大小相等的两块,每次使用其中的一块,当这块内存用完就将存活的对象复制到另一块内存上,然后八这块内存上所有的对象一次清除。减少了标记遍历的时间,但是将内存缩小一半,代价太大。如果半区的对象全部存活,复制消耗的时间代价不小。

标记整理算法

根据老年代的特点,标记过程和标记清除算法一致,但后续不是对可回收对象进行回收,而是让所有存活的对象都想一端移动,然后直接清理掉另一边的内存。但是效率上不如复制算法。

分代收集算法

按照对象的存活周期不同将内存划分为几块,一般是新生代和老生代,永久代的手机效果很差所以一般很少对永久代进行垃圾回收,根据个年代的特点采用最合适的收集算法。新生代采用复制算法,老生代采用标记整理或者标记清除算法来回收。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值