Java 语言的一大特点就是可以自动回收垃圾。
一下列举了垃圾回收器的算法以及实现原理:
引用计数器算法
引用计数器的实现很简单,只要在每一个对象上添加一个整形的计数。当有地方引用这个对象的时候,计数器+1,当引用失效的时候,计数器-1。当计数器为0,表示没有对象引用,垃圾回收器会回收这个对象。
注意: 引用计数器不能处理循环引用的情况。
根搜索方法:
根搜索方法是通过一些“GC Roots”对象作为起点,从这些节点开始往下搜索,搜索通过的路径成为引用链(Reference Chain),当一个对象没有被GC Roots的引用链连接的时候,说明这个对象是不可用的。
GC Roots对象包括:
a) 虚拟机栈(栈帧中的本地变量表)中的引用的对象。
b) 方法区域中的类静态属性引用的对象。
c) 方法区域中常量引用的对象。
d) 本地方法栈中JNI(Native方法)的引用的对象。
2. 标记清除算法(Mark-Sweep)
标记-清除算法分为两个部分,一个是标记,一个是删除。
- 标记阶段: 确定所有需要回收的对象,并标记。
- 清除阶段: 清除阶段紧随标记阶段,回收所有标记过的对象。
**特点: **
标注清除阶段的效率不高,而且删除过后,会产生很对不连续的内存空间。
垃圾回收前:
[图片上传失败...(image-43e8ff-1540177549428)]
垃圾回收后:
[图片上传失败...(image-34f05b-1540177549428)]
标记-复制算法(Copy)
复制算法是将内存分为两块大小相等的内存。在垃圾回收之后,将存活的对象复制到另一块内存空间,清除这块内存。
**特点: **
复制算法运行简单,实现高效,但是内存利用率不高,每次只能使用一半。现在的JVM使用复制的算法收集新生代,由于新生代大部分内存时间都是短暂的,所以两块内存的大小不是1:1(大概是8:1)。
垃圾回收之前:
[图片上传失败...(image-328288-1540177549428)]
垃圾回收之后:
[图片上传失败...(image-d73d4c-1540177549428)]
3. 标记-整理算法(Mark-Compact)
标记压缩算法可标记复制算法类似,但是标记整理算法不是将存活对象复制到另一半的内存,而是将存活对象向内存的一端移动,然后回收边界以外的内存。
**特点: **
标记整理算法提高了内存的利用率,而且这种算法比较适合生命周期比较长的老年代。
垃圾回收之前
[图片上传失败...(image-b3c694-1540177549428)]
垃圾回收之后
[图片上传失败...(image-5aa53e-1540177549428)]
分代收集( Generational Collection)
分代手机是将内存分为新生代和老生代,根据个对象的存活特点,每个待采用不同的算法。
新生代采用的是: 标记-复制算法。两块内存的大小比例大概(8:1)
老生代采用的是: 标记-整理算法。