java垃圾回收
Posted 白豆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java垃圾回收相关的知识,希望对你有一定的参考价值。
java垃圾收集
-
首先我们来思考一下什么对象是垃圾需要被回收?
-
引用计数算法
每个对象都会有一个整形值用来记录当前他被几个reference类型所持有,当该整型值为0时就表示该对象要被回收。这种回收算法有的明显问题就是存在循环引用的现象,比如A的一个Field是B,B的Filed是A,这样俩个对象就无法被正确判断并回收。
-
可达性分析算法
从GC Root 对象开始所有可以被访问到的都是要被使用的,而剩下的对象就是要被回收的。
而可以作为GC Root 的对象 包括如下几类:
- 静态变量
- 虚拟机中栈所引用的对象。注意:如果对象不存在逃逸的可能使用标量替换在栈上创建,这样效率很高,对象在堆上创建的一个主要原因是为了线程共享,如果不需要)
- 常量
- class对象
当一个对象被标记为死亡时,垃圾回收就会尝试在第一次收集其时尝试调用它的finalize()方法,在这个方法中被回收的对象可以尝试自救,或者通知自己快被回收了。如果这个对象没有重写该方法就直接被回收,如果对象重写了该方法,就会再第二次的该对象被标记为死亡时回收。注意一个对象只有一次自救的机会,即使它第一次自救成功,如果它再次被标记为死亡就不会再调用该方法。
-
标记清除算法:
标记清除算法分为两个阶段:
标记阶段:
使用可达性方式并使用深度优先遍历算法,将所有active对象标记为active。
清除阶段:
将查看对象是否active不是的话就直接把它分片,并将地址添加到可用内存链表(可用空闲链表)上,这样分配对象,就直接从可用空闲链表上找合适大小的空间并分配。清楚阶段并不会将回收的内存全部置为0,将内存全部置为0应该在创建对象的阶段应该为:刚为对象分配完内存空间之后。
缺点:
碎片化问题,对象分配速度
标记复制算法:
- 第一阶段类似:
- 不同的是,该收集算法会将内存分为两块,第二阶段会将正在使用的这块内存中未被收集的对象,复制并整齐排列到另一块大小相等的内存。
- HotSpot的实现是将新生代分为三块内存,分别为eden,survivor from,survivor to,碧莉为8:1:1,因为标记复制算法在存活对象比较少的时候效率很高,新生代中的对象又比较短命因此比较适合新生代的回收。当对象刚被创建时,分配在eden上(如果eden内存不够就直接分配在老年代),survivor from 中存放上次回收剩下的对象,本次的survivor from 也就是 上次的 survivor to。对象熬过的垃圾回收次数比较多就可能被弄到老年代。
- 优缺点:对象存活率低时比较高效,当时空间浪费也是明显的。(降低Survivor 的比例就是在减少空间浪费 )
标记整理算法:
标记阶段差不多,但是接下来就要将存活的对象,移向内存一边(紧密排列)
serial:采用串行的方式收集垃圾,会STW。parallelScavenge采用并行的方式收集垃圾但是仍然会STW。parNew,结合CMS和Serial进行收集垃圾。
以上是关于java垃圾回收的主要内容,如果未能解决你的问题,请参考以下文章
Java学习笔记3.11.2 垃圾回收 - 垃圾回收的实现方式
53.垃圾回收算法的实现原理启动Java垃圾回收Java垃圾回收过程垃圾回收中实例的终结对象什么时候符合垃圾回收的条件GC Scope 示例程序GC OutOfMemoryError的示例