对于不再有用的对象,Java有垃圾自动回收机制(Garbage Collection,GC)。哪些东西会被垃圾收集器 (Garbage Collector)认定为不再有用的对象?简单地说,任何无法被JVM中正在执行的线程通过引用变量名追寻到的对象,就是GC认定的垃圾。
具体来讲,在Java中采取了可达性分析法。原理是通过一系列的“GC Roots”对象作为起点进行搜索,如果在“GC Roots”和一个对象之间没有任何可达路径,则称该对象是不可达的,但是要注意,被判定为不可达的对象不一定就会成为可回收对象。被判定为不可达的对象要成为可回收对象必须至少经历两次标记过程,如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。
本文只是简单示例对象成为垃圾的情形,通常情况,在启动JVM之后,JVM中就会有一些执行线程,最基本的,就是程序执行入口的主执行线程(main thread),基本上,main 主线程是你要关心对象是否成为垃圾的起点。
假设有一个类:
public class Some {
Some next;
}
如果在main 方法中有这样一段代码:
Some some1 = new Some();
Some some2 = new Some();
Some some1 = some2;
执行到第二行时,主线程通过变量名可达对象为:
执行到第三行时,是将some2对象赋值给some1,这时some1指向some2:
这个时候,原先被some1引用的对象不再被任何变量引用,通过主线程也不再可以找到该对象,这个对象就是内存中的垃圾了,GC会自动找出这些垃圾并予以回收。
小编给大家推荐一个学习氛围超好的地方,java交流:一四四九零一零七六!适合在校大学生,小白,想转行,想通过这个找工作的加入。里面资料都是大家贡献的,几百个G了!什么PDF,零基础入门,都是有视频加源码的。而已里面好多学生,工作了的,遇到bug了可以寻求帮助,遇到解决不了的问题也可以和大家交流,从而解决自己多时的问题。
如果是建立的新的线程,例如:
在someMethod()执行过后,只要建立的执行线程还没有离开run()方法,也就是执行线程还没进入dead状态,则该执行线程所引用的对象就一直还可以利用,也就不会被垃圾回收。
如果有这样一段代码:
Some some = new Some();
some.next = new Some();
some = null;
在执行到第二行时,情况为这样:
当执行到第三行时,变为这样:
这个时候,some原先所引用的对象,会被回收,而next所引用的对象也因无法被任何线程可达,也会被回收。所以同样地道理,下面的代码中,对象数组所引用到的对象全部都会被回收:
Some[] somes = ;
somes = null;
还有一种情况,形成孤岛的对象,例如:
Some some = new Some();
some.next = new Some();
some = null;
当执行到第四行代码时,
当执行到第五行代码时,
这个时候右边的对象形成了一个孤岛,将全部被GC给回收掉。