共计 1411 个字符,预计需要花费 4 分钟才能阅读完成。
对象生与死
明天不是给 大家介绍对象 的,给大家介绍下垃圾,因为垃圾会霸占内存,需清理之,明天咱们聊聊 JVM 用什么形式回收垃圾的!先上图吧,咱们看看对象的生命周期。
先解释几个名词:
- 新生代:疾速成长,寄存年纪比拟小的对象。
- 老生代:寄存年纪比拟大的对象。
- Surviror:回收新生代内存后包容其余存活的对象,分为 From 区和 to 内存区。
新生的对象都在 eden 区,当 eden 区满时包容不了大的对象,会触发 GC,如果对象还活着,小对象进入 From 区或者是 to 区,这两块区域有一块是空的,假如当初装对象是 from 区,那么,当 GC 后 from 区所有对象会复制到 to 区,并且清空 from 区域,存活对象年纪会增大一岁,当对象达到肯定年纪之后,就会进入老年代了。如果对象比拟大,Surviror 装不下,会间接进入老年代,如果老年代也装不下,会报错:堆内存溢出。
简略介绍垃圾生命周期后,咱们看看垃圾清理算法。
援用计数法
援用计数法怎么判断一个对象是垃圾?就看是否有援用指向该对象。援用计数法示意如果一个对象有 1 个援用计数器就是 1,2 个援用计算器是 2,如果没有援用,计数器为 0,也就是垃圾对象。毛病是对象互相援用,对象无奈回收。画图举个简略案例。
如上图代码:teacher 持本身援用同时持有 student 的援用,计数器为 2,student 持本身援用同时持有 teacher 的援用,计数器为 2,这叫互相援用,最终导致 teacher 或者 student 对象都无奈被回收。所以当初垃圾回收器个别不采纳援用计数法。
标记 - 革除法
标记 - 革除分两步,GC 线程先标记可达对象,当产生 GC 时,革除不可达对象。毛病 是回收后内存碎片。
如上图,咱们晓得分配内存都是间断的,垃圾对象回收后,内存很不规则,不利于内存应用效率。垃圾对象是不可达的?那什么叫可达对象呢,什么叫不可达对象呢?
- 可达对象:从根援用搜寻,能达到的对象叫可达对象,如绿色存活对象叫可达对象。如果从根援用搜寻,
- 不可达对象:不能达到的对象叫不可达对象。如黄色局部,就是垃圾对象,特地留神:此黄非彼黄。
- 根 援用:也叫 GC root,寄存在栈中,指向堆的援用,个别用参数或者局部变量示意。
理论性的货色还是比拟难了解,咱们画图示意下。
假如:new Object()对应的堆地址是 0xJL。
Object object = new Object(); 栈 object 援用指向 new Object()对应的 0xJL 地址,new Object()对象可达,其中object 就叫做根对象。
object = null; 通知 gc 线程,没有援用指向 0xJL 了,那这块内存就有可能被标记为垃圾对象。
复制算法
复制算法须要将一块空白的内存一分为二,GC 后,将可达对象全副挪动到另一块内存。新生代对象朝生夕死,GC 后将活着的对象挪动到另一块空内存,并将以后应用的内存清空。每次 GC,周而复始。
如上图:新生代采纳复制算法,GC 回收前应用 from 区域,GC 后应用 to 内存区域。
标记整顿法
标记整顿算 法基于标记革除算法做了肯定优化,gc 线程首先从根节点开始标记可达对象,并将可达对象压缩到内存顶部,最初革除边界区域,老年代对象生命周期长,比拟实用于 标记整顿算 法。
如上图:当老年代满了,会触发 Full GC,将内存压缩整顿。
总结
画图解释了几种 GC 算法的含意和毛病,心愿对你有帮忙,喜爱的请点赞加关注哦。点关注,不迷路,我是【叫练 】 公众号 ,微信号【jiaolian123abc】 边叫边练。