- 前言
- 四种引用类型
- 强引用
- 软引用
- 弱引用
- 虚引用
- 垃圾回收算法
- 1. 标记-清除算法
- 2. 复制算法
- 3. 标记-整理算法
- 4. 分代算法
- 收集器
前言
提到JVM就肯定要提垃圾回收,内存的自动管理,是很多高级语言的一大特性,对于不同的应用,组合不同的回收算法,不单是体现对JVM的理解,也是非常有趣的过程
四种引用类型
对于Java的引用类型还是有必要了解的,因为不同的类型会影响到回收的策略
强引用
这是Java中最常见的引用类型,一个对象赋值给一个变量,这个引用变量就是一个强引用
当一个对象被强引用变量引用时,即处于可达状态,它是不可能被垃圾回收机制回收的,即使该对象以后永远不会用到JVM也不会回收。所以这也是造成Java内存泄漏的主要原因之一
软引用是通过继承SoftReference类来实现的,用来描述一些有用但并非必须的对象。对于这类对象来说,当内存足够时,它是安全的。但如果系统内存空间不足时,它就会被回收
弱引用软引用是通过继承WeakReference类来实现的,它的生命周期较软引用更短,只要垃圾回收机制一运行,不管JVM的内存空间是否充足,它都会被回收
虚引用也称为幽灵引用或者幻影引用(听着挺屌),然而是最弱的一种引用关系
是通过继承PhantomReference类来实现的,不能单独使用,必须和引用队列联合使用,主要的作用就是跟踪对象被垃圾回收的状态
垃圾回收算法
对引用类型咱们心里有数了,下面咱们看看都有哪些垃圾回收的算法:
1. 标记-清除算法这个也是最基础的收集算法了,后续的收集算法发展,基本都是由它演变、优化而来的
如同名字一样,分为两个阶段:先标记,再清除
,先找到需要回收的对象进行标记,然后统一回收
缺点:
- 效率不高,两个阶段的效率都一般
- 标记后,会产生很多不连续的内存碎片,导致后续分配大对象时,无法分配进而触发再次回收
方式是将内存分为大小相等的两块,每次只使用其中的一块,当一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把之前的内存空间一次清理掉,现在的商业虚拟机基本都用这种来处理新生代
IBM公司专门研究表明了新生代的对象98%都是朝生夕死的,所以就演变出了之前提到的Eden和From Survivor和To Survivor空间,而默认的8:1:1这样的黄金比例,也应该是通过大量的实践数据得来的最优解
3. 标记-整理算法与标记-清除类似,只不过并不是直接对可回收对象进行清理,而是让所有存活的对象都向一断移动,然后直接清理掉端边界意外的内存
4. 分代算法当前商业虚拟机的垃圾收集采集基本都采用了这种算法,改变了以往的分区逻辑,改为分代逻辑
即根据对象存活周期的不同将内存划分为几块
一般是把Java堆分为新生代和老年代,然后根据各个年代的特点采取适当的收集算法
收集器
上边就是方法论,收集器就是具体实现了
- Serial:最基础的垃圾收集器,是
单线程+复制算法
- ParNew:它其实就是Serial的多线程版本
- Parallel Scavenge:同样是
多线程+复制算法
,区别是它重点关注的是程序达到一个可控制的吞吐量 - Serial Old:它用的是
单线程+标记-整理算法
,主要是Client端默认的JVM老年代垃圾收集器 - Parallel Old:从名字也可以看出来它是Parallel Scavenge的老年代版本,使用的是
多线程+标记-整理算法
- CMS:使用的是
多线程+标记-清除算法
- G1:当下最流行的收集器,横跨新老两代,基于
并行+标记-整理算法
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)