前奏
- 提到Java的垃圾回收机制,必须要提到Java的内存管理模型,详见 Java-面试--Java8-JVM内存模型
Java垃圾回收
Garbage Collection,GC
为什么要进行垃圾回收
- 随着程序的运行,内存中存在的实例对象、变量等信息占据的内存越来越多,如果不及时进行垃圾回收,必然会带来程序性能的下降,甚至会因为可用内存不足造成一些不必要的系统异常。
哪些垃圾需要回收
- 有三个区是不需要进行垃圾回收的,分别是:程序计数器、JVM栈、本地方法栈。
- 需要进行回收垃圾的区:堆和方法区
什么时候进行垃圾回收
- 什么样的类需要回收呢?无用的类,何为无用的类?需满足如下要求:
1> 该类的所有实例对象都已经被回收。
2> 加载该类的ClassLoader已经被回收。
3> 该类对应的反射类java.lang.Class对象没有被任何地方引用。
常见的GC算法
- 标记-清除算法(Mark-Sweep)
- 最基础的GC算法,将需要进行回收的对象做标记,之后扫描,有标记的进行回收,这样就产生两个步骤:标记和清除。这个算法效率不高,而且在清理完成后会产生内存碎片,这样,如果有大对象需要连续的内存空间时,还需要进行碎片整理,所以,此算法需要改进。
- 复制算法(Copying)
- 前面我们谈过,新生代内存分为了三份,Eden区和2块Survivor区,一般Sun的JVM会将Eden区和Survivor区的比例调为8:1,保证有一块Survivor区是空闲的,这样,在垃圾回收的时候,将不需要进行回收的对象放在空闲的Survivor区,然后将Eden区和第一块Survivor区进行完全清理,这样有一个问题,就是如果第二块Survivor区的空间不够大怎么办?这个时候,就需要当Survivor区不够用的时候,暂时借持久代的内存用一下。此算法适用于新生代。
- 标记-整理(或叫压缩)算法(Mark-Compact)
- 和标记-清楚算法前半段一样,只是在标记了不需要进行回收的对象后,将标记过的对象移动到一起,使得内存连续,这样,只要将标记边界以外的内存清理就行了。此算法适用于持久代。
常见的GC回收器
垃圾回收算法.jpg- GC主要分二类,新生代GC,老年代GC;
- 新生代GC包括:串行GC、并行GC、并行回收GC;
- 老年代GC包括:串行GC、并行GC、CMS;
- G1比较特殊,同时支持新生代和老年代。
GC和OOM的区别
Java Minor GC、Major GC和Full GC之间的区别?
- Minor GC
- Minor GC指新生代GC,即发生在新生代(包括Eden区和Survivor区)的垃圾回收操作,当新生代无法为新生对象分配内存空间的时候,会触发Minor GC。因为新生代中大多数对象的生命周期都很短,所以发生Minor GC的频率很高,虽然它会触发stop-the-world,但是它的回收速度很快。
- Major GC
- Major GC清理Tenured区,用于回收老年代,出现Major GC通常会出现至少一次Minor GC。
- Full GC
- Full GC是针对整个新生代、老生代、元空间(metaspace,java8以上版本取代perm gen)的全局范围的GC。Full GC不等于Major GC,也不等于Minor GC+Major GC,发生Full GC需要看使用了什么垃圾收集器组合,才能解释是什么样的垃圾回收。
网友评论