java垃圾收集器及原理

很多面试题一问垃圾回收器就会套用三个问题:“哪些内存需要回收?”“什么时候回收?”及“如何回收?”。那么理解垃圾回收器及原理,解答这三个问题是不必可少的了。

不过首先,Java内存的动态分配和垃圾回收已经是自动化的了,平时编写代码的过程中根本就感觉不到它的存在,为什么还要去理解垃圾回收器呢?因为代码中的很多问题,比如内存溢出,内存泄漏等,垃圾回收赶不上内存的使用速率的时候,就需要去考虑垃圾回收器了。

垃圾回收器主要工作区域是堆和方法区

Java运行时内存区域的虚拟机栈和本地方法区,程序计数器跟线程相关,随线程生死。所以,该区域不是GC工作的主要区域。GC工作的主要区域是存放对象的堆和和存放类信息的方法区。

哪些内存需要回收?

内存的回收主要是回收不再使用的对象。那么如何判断哪些对象不再使用呢?

GC使用的是可达性分析算法,很多人熟悉引用计数算法,但这个不是GC使用的,因为它存在相互引用无法被回收的问题。

可达性算法:从一个叫做“GC Roots”的对象开始往下搜索,如果有对象没有到CG Roots的链路,就说明这个对象是不可用的,是垃圾回收器需要回收的对象。

对象的标记
不可达对象的两次标记过程,之后才会被回收,可以在第一次标记后通过重构的finalize()复活。不推荐使用。

什么时候回收?

  1. GC堆中新生代空间不足以存放一个对象时,将发生内存回收
  2. 经常性的大对象出现,会导致内存还有不少空间时,就触发垃圾回收来确保内存中有连续空间来存放大对象

如何回收?

标记清除算法
问题:1、效率问题。2、空间问题,产生大量不连续的内存片段,对于大对象不好存放。

标记整理算法
将存活的对象移动到内存的一端,然后清除掉其他内存。

复制算法
将内存分为两块,一次就用一块。每次回收将存活的对象复制到另一半内存中,再清空上次使用的内存。
问题:内存可使用空间为原来的一半。

分代收集算法
当前商业虚拟机的垃圾回收都采用“分代收集”算法,将对象存活周期不同在内存中分为几块。一般是把Java堆分为新生代和老生代。一般新生代中对象死亡概率大,所以使用复制算法,提高回收效率,而且复制成本低。而老年代因为对象存活几率大,所以使用“标记-清理”或者“标记-整理”算法回收。

内存空间

  • 新对象一般被放在新生代,除非特别大的对象会被放到老年代。
  • 每发生一次垃圾回收,没有被回收的新生代对象将进入survivor区域,同时该对象的age属性值为1。该对象每熬过一次GC,age就加1,默认age等于15时,该对象就进入老年代。如果Survivor空间中,相同年龄的对象大小的总和大于Survivor空间的一半,年龄大于等于该年龄的对象就可以直接进入老年代。

你可能感兴趣的:(java垃圾收集器及原理)