有 GC Roots 引用的对象不能回收,没有 GC Roots 引用的对象可以回收,如果有 GC Roots 引用,但是如果是软引用或者弱引用的,也有可能被回收掉。
1. 什么时候会触发垃圾回收?
如果新生代快填满了,就会触发垃圾回收,把新生代里没有人引用的对象给回收掉,释放空间;
2. 垃圾回收时,哪些对象是能回收的,哪些对象是不能回收的?
- JVM 中使用了一种可达性分析算法来判定:
- 对每个对象,都分析一下有谁在引用他,然后一层一层往上去判断,看是否有一个 GC Roots,如果有,就不能回收;
- 在 JVM 规范中,方法的局部变量就是可以作为 GC Roots 的;
- 在 JVM 规范中,类的静态变量也可以看做是一种 GC Roots;
- 注意:类的实例变量不是 GC Roots;
- 总结:只要你的对象被方法的局部变量、类的静态变量给引用了,就不会回收他们;
3. Java 中对象不同的引用类型与垃圾回收的关系
强引用:垃圾回收的时候绝对不会去回收这个对象的;
- 一个变量引用一个对象;
public class Kafka{
public static ReplicaManager replicaManager = new ReplicaManager();
}
- 一个变量引用一个对象;
软引用:正常情况下,垃圾回收是不会回收软引用对象的,但是如果你进行垃圾回收之后,发现内存空间还是不够存放新的对象,内存都快溢出了。此时就会把这些软引用对象给回收掉,哪怕他被变量引用了,但是因为他是软引用,所以还是要回收。
- 把“ReplicaManager”实例对象用一个“SoftReference”软引用类型的对象给包裹起来了,此时这个“replicaManager”变量对“ReplicaManager”对象的引用就是软引用了;
public class Kafka{
public static SoftReference<ReplicaManager> replicaManager =
new SoftReference<ReplicaManager>(new ReplicaManager());
}
- 把“ReplicaManager”实例对象用一个“SoftReference”软引用类型的对象给包裹起来了,此时这个“replicaManager”变量对“ReplicaManager”对象的引用就是软引用了;
弱引用:弱引用就跟没引用是类似的,如果发生垃圾回收,就会把这个对象回收掉;
- 虚引用:很少用;
这里比较常用的,就是强引用和软引用,强引用就是代表绝对不能回收的对象,软引用就是说有的对象可有可无,如果内存实在不够了,可以回收他。
3. finalize()
假设一个对象要被垃圾回收了,会先尝试调用它的 finalize() 方法;
如果在 finalize() 中把自己这个实例对象指定一个 GC Roots 变量,那就又不会被垃圾回收了;
public class ReplicaManager {
public static ReplicaManager instance;
@Override
protected void finalize() throws Throwable {
ReplicaManager.instance = this;
}
}