我已经在无数地方读过,运行线程是垃圾收集根(即它们驻留在堆栈上,GC识别它们并跟踪它们以确定它们内部的对象是否仍然可以访问)。此外,GC根目录永远不会被垃圾收集。
我的困惑在于:如果从线程内部分配的对象永远不会被垃圾收集,直到线程被停止,那么如何在单线程程序中收集任何垃圾,其中唯一的线程是主线程?
显然我在这里遗漏了一些东西。
答案 0 :(得分:1)
对象在堆中,无论哪个线程创建它们。
可以通过引用访问对象。其中一些引用可以在一个或多个线程的调用堆栈上。
当没有更多对它的引用时,可以收集一个对象,无论分配线程是否仍在运行。
例如,下面的线程重复分配新的StringBuilder对象。在调用foo()期间,线程在其调用堆栈上引用了StringBuilder对象。当foo()
返回时,没有对StringBuilder对象的进一步引用。因此,该对象不再可访问,并且符合条件用于垃圾回收。
Thread thread = new Thread( new Runnable() {
@Override
public void run() {
while ( true ) {
foo();
}
}
public void foo() {
StringBuilder strBuilder = new StringBuilder("This new object is allocated on the heap.");
System.out.println( strBuilder );
}
});
thread.run();
答案 1 :(得分:1)
首先,线程(堆栈)只有GC根目录才有效。当线程终止时,它不再是GC根目录。
我的困惑在于:如果从线程内部分配的对象永远不会被垃圾收集,直到线程被停止,那么如何在单线程程序中收集任何垃圾,其中唯一的线程是主线程?
你的前提不正确。
哪个线程分配对象并不重要。重要的是您的线程分配的对象是否仍然可以访问。如果它变得无法访问(例如,如果你没有将对象的引用放入局部变量中)......那么就可以收集它。