JVM篇3:GC

本文主要介绍对象垃圾回收机制

1.Minor Gc和Full GC 有什么不同呢?

  • 大多数情况下,对象在新生代Eden区进行分配,当Eden去没有足够的空间进行分配时,虚拟机将发起一场Minor GC。
    (1)新生代GC(Minor GC):指发生在新生代的垃圾回收动作,Minor GC非常频繁,回收速度也较快。
    (2)老年代GC(Major GC/Full GC):指发生在老年代的GC,出现了Major GC经常会伴随至少一次的Minor GC(并非绝对),Major GC的速度一般会比Minor GC慢10倍以上。

2.如何判读对象是否死亡?

2.1引用计数法

  • 给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加1,当引用失效,计数器就减1,当计数器为0的时候对象就判定是死亡了。

2.2可达性分析法

  • 基本思想就是通过一系列的称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,节点走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连的话,则认为此对象已死。
    JVM篇3:GC

3.四大引用类型:强引⽤,软引⽤,弱引⽤,虚引⽤

JVM篇3:GC

3.1强引⽤(StrongReference)

  • 如果⼀个对象具有强引⽤,那就类似于必不可少的⽣活⽤品,垃圾回收器绝不会回收它。当内存空 间不⾜,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终⽌,也不会靠随意回收具有强引⽤的对象来解决内存不⾜问题。

3.2软引⽤(SoftReference)

  • 如果⼀个对象只具有软引⽤,那就类似于可有可⽆的⽣活⽤品。如果内存空间⾜够,垃圾回收器就不会回收它,如果内存空间不⾜了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使⽤。软引用可以用来实现内存敏感的高速缓存。
  • 软引用可以和一个引用序列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

3.3弱引⽤(WeakReference)

  • 如果⼀个对象只具有弱引⽤,那就类似于没啥用的⽣活⽤品。**和软引用的区别在于:只具有弱引用的对象的生命周期更短,不管当前内存空间够不够,GC时都会将它回收。**不过,垃圾回收器是一个优先级很低的线程,因为不一定能很快以发现那些只具有那些弱引用的对象。
  • 弱引⽤可以和⼀个引⽤队列(ReferenceQueue)联合使⽤,如果弱引⽤所引⽤的对象被垃圾回收,Java虚拟机就会把这个弱引⽤加⼊到与之关联的引⽤队列中。

3.4虚引⽤(PhantomReference)

  • "虚引⽤"顾名思义,就是形同虚设,与其他⼏种引⽤都不同,虚引⽤并不会决定对象的⽣命周期。如果⼀个对象仅持有虚引⽤,那么它就和没有任何引⽤⼀样,在任何时候都可能被垃圾回收。虚引用主要用来跟踪对象被垃圾回收的活动。
  • 虚引⽤与软引⽤和弱引⽤的⼀个区别在于: 虚引⽤必须和引⽤队列(ReferenceQueue)联合使⽤。当垃圾回收器准备回收一个对象的时候,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引⽤已经被加⼊到引⽤队列,那么就可以在所引⽤的对象的内存被回收之前采取必要的⾏动。
  • 特别注意,在程序设计中⼀般很少使⽤弱引⽤与虚引⽤,使⽤软引⽤的情况较多,这是因为软引⽤可以加速JVM对垃圾内存的回收速度,可以维护系统的运⾏安全,防⽌内存溢出(OutOfMemory)等问题的产⽣。

4. 如何判断⼀个常量是废弃常量?

  • 运⾏时常量池主要回收的是废弃的常量。那么,我们如何判断⼀个常量是废弃常量呢?
    假如在常量池中存在字符串 “abc”,如果当前没有任何String对象引⽤该字符串常量的话,就说明常量"abc" 就是废弃常量,如果这时发⽣内存回收的话⽽且有必要的话,“abc” 就会被系统清理出常量池。

5.如何判断一个类是无用的类?

  • 方法区主要回收的是类。那么如何判断一个类是无用的类呢?这里的情况比较苛刻,需要下列3个条件同时满足才行。
    (1)该类的所有实例都已经被回收,也就是Java堆中不存在该类的任何实例。
    (2)加载该类的ClassLoader已经被回收。
    (3)该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。