思维导图
垃圾收集器
提供一种用于在空闲时间不定时回收无任何对象引用占据的内存空间的一种机制
停止-复制算法
程序先停止,将存活对象从一个堆复制到另外一个堆,剩下的就都是垃圾。(对象转移之后所有指向该对象的引用都需要修改)
算法问题:
- 需要有两个堆,在两个堆之间来回复制内存,比实际需要多一倍内存
- 一旦程序变得稳定它可能很少产生垃圾,甚至没有。尽管如此,复制收集器仍然会将所有内存从一个地方复制到另外一个地方,这是一种浪费
标记-清除算法
该算法从栈和静态存储开始,遍历所有引用以查找存活对象。每当他找到一个存活对象,就会给该对象设置一个标志。此时尚未开始收集,只有标记过程完成之后才会进行清除操作。在清除操作中,没有被标记的对象会被清除,但不会发生复制。
算法问题:
- 对于一般用途,'标记-清除’算法相当慢,在垃圾很少或者说根本没有垃圾的时候,它的速度很快
分代算法
创建一个对象的时候在’Eden’区操作,当这个区满了之后,触发Young CG,也就是年轻代的垃圾回收。
当Eden区再次被用完的时候,会再触发一次Young CG ,此时会将Eden 区与From区还在被使用的对象复制到To区。
在下一次Young CG 的时候,将Eden与To区中还在被使用的对象复制到To区。
若干次Young CG后,有些对象会在From与To之间来回游荡,一旦超过阈值,就会将他们复制到老年代。如果老年代被用完,就会执行一次Full CG
自适应算法
JVM会监控垃圾回收的效率,如果对象都很稳定,垃圾收集器效率很低的话就会切换到 ‘标记-清除’ ,同样如果堆内出现很多垃圾碎片时,会切换到 ‘停止-复制’。
资源清理
C++ VS Java
额外清理
假设对象不适用 new 的情况下,分配了一块特殊内存。垃圾收集器只知道如何释放由 new 分配的内存,不知道如何释放不由 new 创建的特殊内存。
清理方法
- 使用finalize()方法
- 介绍:清理资源,但不等同于C++的析构函数,他会被GC自动调用()
- 适用情况:对象以某种特殊方式分配了内存,GC不知如何释放他。
- 备注:java语言规范不保证finalize()会被及时执行,也不保证一定会执行,永远不要直接调用!!!
- 显示调用
- 终止对对象封装的资源(文件、线程),最好提供一个显示的关闭方法,如显示定义一个close()方法
总结
- 在java中始终使用 new 创建对象,垃圾收集器会自动释放存储空间。
- 如果在java中通过其他机制创建了一个对象,使用finalize()管理内存空间的释放,由垃圾收集器自动调用。
- 如果需要终止对象封装的资源(文件、线程),提供一个显示的终止方法。