概述
引言
java和c++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进来,里边的人想出去
一.简介
垃圾收集,也叫作GC(Garbage Collection),历史久远,甚至比java历史还要长,因此,第一门使用垃圾收集的语言并不是java,而是Lisp
垃圾收集需要完成的三件事:
- 哪些内存需要回收?
- 什么时候回收?
- 如何回收?
二.判断哪些内存需要回收及什么时候回收?
判断哪些内存需要回收,其实就相当于判断哪些对象还存活着,哪些对象已经死亡,对死亡对象进行回收
判断对象是否存活的两个经典算法:
1.引用计数法
-
思路:
给对象中添加一个引用计数器,每当一个地方饮用该对象,该对象的引用计数器数值+1,当引用失效(eg:object = null)则该对象的引用计数器数值 -1;任何时刻当一个对象的引用计数器为0时,则表示该对象是没有被使用的,则可以回收这个对象。
-
缺陷:、
1.难以解决对象的循环引用问题
Aobject obj1 = new Aobject();
Bobject obj2 = new Aobject();
obj1.objectFiled = obj2;
obj2.objectFiled = obj1;
这样,obj1对象引用了一次obj2,引用计数器数值 +1,但是obj1对象也被obj2对象引用了一次,obj2引用计数器数值+1,他们因为相互引用着对方,所以引用计数器数值一直不为0,所以也无法通知gc收集他们。
2.可达性分析法
//上述代码之下,手动调用gc
System.gc();
如果是引用计数法,gc是不成功的,但是,事实上虚拟机并没有因为他们对象相互引用而不回收他们,所以,虚拟机并不是通过引用计数法进行对象存活判断。
-
思路:
该算法有一个GC Roots对象集合,仍然存活的对象会以一个GC Roots对象作为引用链的起始节点,而没有与GC Roots对象建立引用关系则判断为可回收对象
-
补充:
java引用分类:
- 1 强引用 ---- 即对象实例化(
Object o = new Object()
)只要强引用存在,垃圾收集器不会回收被引用对象 - 2 软引用 ---- 一些还有用但是暂时没用到又不是必须的对象,在系统将要发生内存溢出前,这些对象会放进回收名单进行第二次回收,如果回收了这部分内存还是内存不足,则抛出异常。
- 3 弱引用 ---- 无论当前内存是否足够,都会回收被弱引用的对象
- 4 虚引用 ---- 设置虚引用的唯一目的就是能在这个对象被收集前收到一个系统通知
- 1 强引用 ---- 即对象实例化(
三.如何回收?
从前面知道了如何判断哪些对象需要回收了,现在要做的就是回收这些对象。
1.垃圾收集算法
垃圾回收主要依赖于垃圾回收算法
1.标记 - 清除 算法
-
思路:
找出所有要回收的对象,进行标记,将标记的对象通通回收 -
缺陷:
1 效率低
2 会产生大量不连续的内存空间(碎片),导致以后如果要分配大对象时无法找到一片足够大的内存空间
2.复制算法
-
思路:
他将可用的内存空间分为大小相等的两块,每次只使用其中的一块,当这一块的内存用完了,就将这一块上还存活着的对象复制到另一块上,最后再把刚刚使用完的那一块内存空间一次清理掉 -
缺陷:
解决了标记 - 清除 算法的效率问题,但是牺牲了内存
3.标记 - 整理 算法
- 思路:
标记部分和标记 - 清除 算法一样,但是后续的整理却不是直接将可回收的对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存
4.分代收集算法
- 思路:
根据对象存活周期将内存划分为几块,一般是把堆分为新生代和老年代,根据不同年龄代选择不同的算法
新生代每次垃圾收集都会有大批对象死去,只有少量存活,选用复制算法,只需复制少量存活对象。
而老年代对象存活率高,没有额外空间,选择标记 - 整理或者标记 - 清除算法
2.垃圾收集器总结
1.Serial收集器
- 特点:
- 单线程收集器(当进行垃圾收集时必须暂停其他工作线程,直到完成垃圾收集,这段时间称为停顿时间)
- 简单高效(对于限定单个cpu环境下,由于没有线程交互的开销,可专心做垃圾收集)
- 虚拟机client模式下的默认新生代收集器
2.ParNew收集器
- 特点:
- Serial收集器多线程版本,垃圾收集多线程进行
- 虚拟机server模式下首选新生代收集器
- 使用复制算法
3.Paraller Scavenge收集器
- 特点:
- 新生代收集器
- 使用复制算法
- 并行多线程收集器
- 缩短了垃圾收集和用户线程的停顿时间。(控制吞吐量)
- 具有自适应调节策略来提供最合适的停顿时间或者最大吞吐量
4.Serial Old收集器
- 特点:
- Serial收集器的老年代版本
- 单线程收集器
- 使用标记 - 整理算法
5.Paeallel Old收集器
- 特点:
- Paraller Scavenge收集器的老年代版本
- 多线程收集器
- 使用标记 - 整理算法
6.CMS收集器
- 特点:
- 使用标记 - 清除算法
- 过程:初始标记 -> 并发标记 -> 重新标记 -> 并发标记
- 用户线程和收集线程并发执行,缩短停顿时间
- 对cpu资源敏感,占用cpu资源导致程序变慢
- 无法处理浮动垃圾
7.G1收集器
- 特点:
- 并行与并发(能在多cpu多核环境下减少停顿时间,G1可以通过并发来保证java程序继续执行)
- 分代收集
- 空间整合,总体:标记 - 整理算法,局部:复制算法
最后
以上就是粗犷樱桃为你收集整理的JVM (垃圾收集器分类和总结)的全部内容,希望文章能够帮你解决JVM (垃圾收集器分类和总结)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复