1.如何判断对象是否死亡?
引用计数法
对象中加一个引用计数器,有地方引用它,计数器加1;引用失效,计数器减1;计数器为0的对象就是不能在被使用了。虽然实现简单,效率高,但是难解决对象之间相互循环引用的问题,所以不被JVM采用可达性分析算法
通过一个叫做GC Roots
的对象作为起点,从这个节点向下搜索,节点走过的路径成为引用链,当一个对象到GC Roots没有引用链的话,那么说明该对象要被回收了。
例如Object6~Object10
之间虽有引用关系,但是不能到达GC Roots,所以,它们就是需要被回收的对象。对象可以被回收,但是不一定就代表一定会回收。
2.介绍强引用,软引用,弱引用,虚引用
上述四种引用,引用强度逐渐减弱
- 强引用
就像是我们的生活必需品,垃圾回收器绝不会回收它。就算JVM抛错,也不会随意回收强引用对象 - 软引用
可有可无的生活用品。内存空间足够,垃圾回收器不会回收它;如果不足了,就回收。 - 弱引用
类似可有可无生活用品。 - 虚引用
形同虚设。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。
总结:使用软引用较多,因为软引用可以加速JVM对垃圾内存的回收速度,可以维护系统运行安全,防止内存溢出等问题产生
3.如何判断一个常量是废弃常量?
如果没有任何对象引用的话,那么就是废弃常量
4.如何判断一个类是无用的类?
满足下面三个条件才判定是无用的类:
- Java 堆中不存在该类的任何实例。(该类所有的实例都已经被回收)
- 加载该类的 ClassLoader 已经被回收
- 无法在任何地方通过反射访问该类的方法
5.垃圾收集有哪些算法,各自特点?
-
标记-清除算法
分为标记,清除阶段。先标记不需要回收的对象,标记完成后,统一回收掉所有没被标记的对象。
存在问题:1. 效率问题;2. 空间问题(会产生大量不连续的碎片)
-
标记-复制算法
意义:为了解决效率问题
思想:将内存分为大小相同的两块,每次只使用其中一块。这一块使用完后,标记存活的对象复制到另一块去,然后把使用的空间全部清理。
图解:
但依然存在下面这些问题:
○ 可用内存变小:可用内存缩小为原来的一半。
○ 不适合老年代:如果存活对象数量比较大,复制性能会变得很差
-
标记-整理算法
思想:先标记不需要回收的对象,然后将这些存活对象向一端移动,最后直接清理掉边界以外的内存
图解:
-
分代收集算法(当前虚拟机采用的算法)
思想:根据对象存活周期将内存分为几块。一般将Java堆分为新生代和老年代,然后根据各个代的情况选择合适的回收算法
举例:新生代会有大量对象死去,可以选择
标记-复制
算法。老年代对象存活几率高,没有额外的空间对它进行分配担保,所以必须选择标记-清除
或者标记-整理
算法
6.垃圾收集器
如果说垃圾收集算法是方法论的话,那么垃圾收集器就是内存回收的具体实现