ChatGPT解决这个技术问题 Extra ChatGPT

Java Thread Garbage collected or not

This question was posted on some site. I didnt find right answers there, so I am posting it here again.

public class TestThread {
    public static void main(String[] s) {
        // anonymous class extends Thread
        Thread t = new Thread() {
            public void run() {
                // infinite loop
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                    // as long as this line printed out, you know it is alive.
                    System.out.println("thread is running...");
                }
            }
        };
        t.start(); // Line A
        t = null; // Line B
        // no more references for Thread t
        // another infinite loop
        while (true) {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
            }
            System.gc();
            System.out.println("Executed System.gc()");
        } // The program will run forever until you use ^C to stop it
    }
}

My query is not about stopping a Thread. Let me rephrase my question. Line A(see code above) starts a new Thread; and Line B make the thread reference null. So, the JVM now has a Thread Object(which is in running state) to which no reference exists (as t=null in Line B). So my question is, why does this thread(that has no reference anymore in the main thread) keeps on running until the main thread is running. Per my understanding, the thread object should have been garbage collected post Line B. I tried to run this code for 5 minutes and more, requesting Java Runtime to run GC, but the thread just does not stop.

Hope both the code and question is clear this time.


k
kiranpradeep

A running thread is considered a so called garbage collection root and is one of those things keeping stuff from being garbage collected. When the garbage collector determines whether your object is 'reachable' or not, it is always doing so using the set of garbage collector roots as reference points.

Consider this, why is your main thread not being garbage collected, no one is referencing that one either.


This answer, as it currently stand, raises the question if threads can be GC'ed at all (after they terminate). Since this question is marked as a duplicate of this one, it should be mentioned that threads will no longer be marked as "garbage collection roots" after they terminate, and thus, they become reachable for GC.
Last sentence is penetrating: "why is your main thread not being garbage...".
so as a follow-up, will a disposed thread (one that has been joined) no longer be considered a root? I'm almost certain the answer is yes, but I'm seeing strange things on my application under the profiler and its got me wondering...
The more answers I read, the more confused I get, but yeah why the main thread is not getting garbage collected is something to ponder about. But coming back to core question, if child threads creates some objects it would not getting GCed since the parent thread is still running and holds the references of child threads even if they have 'ran' out (!!??)
@Groostav A thread that has been joined is not running, so it is not a garbage collection root. But when the parent thread called child.join(), it had a reference to child. If that reference (and any other one) is not discarded, the child thread can't be GCed.
T
Thomas Pornin

As was explained, running threads are, by definition, immune to GC. The GC begins its work by scanning "roots", which are deemed always reachable; roots include global variables ("static fields" in Java-talk) and the stacks of all running threads (it can be imagined that the stack of a running thread references the corresponding Thread instance).

However, you can make a thread a "daemon" thread (see Thread.setDaemon(boolean)). A daemon thread is no more garbage-collected than a non-daemon thread, but the JVM exits when all running threads are daemon. One way to imagine it is that every thread, when it terminates, checks whether there remain some non-daemon running threads; if not, the terminating thread forces a System.exit() call, which exits the JVM (killing off the running daemon threads). This is not a GC-related issue; in a way, threads are allocated manually. However, this is how the JVM can tolerate semi-rogue threads. This is typically used for Timer instances.


T
Thilo

The JVM has a reference to all running threads.

No thread (or the things it refers to) will be garbage-collected while it is still running.


v
vy32

The Thread is not garbage collected because there are references to the threads that you cannot see. For example, there are references in the runtime system.

When the Thread is created it is added to the current thread group. You can get a list of Threads in the current thread group, so that is another way to get a reference to it.