垃圾回收算法和gc收集器

-------------- 本文参考自<<深入理解jvm虚拟机>>
判断一个对象是否需要回收,我们可以有2种方式,一种是基于引用计数的,这个我们用的比较多,比如c++的智能指针,但是无法解决循环引用的问题。 另一种是根搜索算法,通过一系列的"root"对象,往下查找引用链。没有被所有"root"对象的引用链连接起来的对象,即可判断为垃圾对象。在java中,可以被认为"gc root"的对象有:

  • 虚拟机栈(栈桢中的本地变量表)中的引用的对象。
  • 方法区的静态属性引用的对象。
  • 方法区中的常量引用的对象。
  • 本地方法栈中jni的引用的对象。

根据对象存在的必需程度,分为强引用,软引用,弱引用,虚引用。软和弱的区别:除非将要发生oom,否则不会清除软引用;弱引用通常在下次gc的时候就回收了。

2.垃圾收集算法

2.1 标记 - 清除法(Mark Sweep)

标记出需要被回收的对象,然后统一清除。 缺点:1.效率不高(为什么?);2.内存碎片。

2.2 复制算法

用两个一样大的内存空间,gc时,将块A存活的对象全部考到块B,然后清除块A。优点:解决标记-清除法的内存碎片问题。缺点:空间利用率50%。

改良方案: 因为新时代的对象98%都是朝生夕死,所以分配一块大的(80%)eden 空间,两块小的(10%)的survivor,将eden和一块survivor的存活对象拷到另一块survivor中,这样空间利用率有90%。问题解决:存活区的空间被压缩了,如果拷贝时survivor空间不够用,那么将直接把当次的所有存活对象考到老年代。

2.3 标记-整理法 (Mark Compact)

和标记-清除法类似。标记完以后,将对象向一端移动,然后直接清除掉边界以外的内存。

3.垃圾收集器

如果两个收集器间存在联系,则他们可以配合使用。3.1-3.3是新生代收集器,后面的收集器用于老年代。

3.1 Serial(连续的)收集器

特点:单线程,复制算法,“stop the world”,高效但是需要一个连续的时间来收集垃圾,以至于无法响应用户代码,适用于client模式。

3.2 ParNew(新式)收集器

特点:Serial的多线程版本,复制算法,“stop the world”,server模式首选,因为只有他和Serial可以配合CMS收集器工作。使用-XX:UseParNewGC 来指定他作为新生代的垃圾回收收集器。

3.3 Paraller Scavenge收集器

和ParNew类似,新生代,复制算法。特点:cpu吞吐量更大,因而适用于计算而不是用户交互。

3.4 Serial Old收集器

Serial的老年代版本,单线程,使用标记-整理法,适用于client模式。

3.5 Paraller Old收集器

Paraller Scavenge 的老年代版本,多线程,使用标记-整理算法,通常配合Paraller Scavenge使用,用于cpu和吞吐量敏感的场合。

默认情况下的垃圾收集器组合。

Server模式: Paraller Scavenge + Paraller Old

Client模式: Serial + Serial Old

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容