6

Is a thread garbage collected when the run() method within the thread is finished or when the function where it was called from finishes?

I don't have an issue or anything, but I want to avoid memory leaks and such.

For people who like code:

public void SomeClass {
    public SomeClass() {

    }

    public void someMethod() {
        Object data = veryBigObject;

        while(true) {
            MyThread thread = new MyThread(veryBigObject);
            thread.run();

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) { /* do nothing */ }
        }
    }

    public static void main(String[] args) {
        SomeClass myclass = SomeClass();
        myclass.someMethod();
    }
}


public class MyThread extends Thread {
    private Object data;

    public Thread(Object data) {
        this.data = data;
    }

    public void run() {
        // do stuff with data
    }
}

In all languages I know, garbage (if the language has any) is collected when a method ends. I assume Java does as well. That means that theoretically the threads I create in someMethod() are not collected until someMethod() ends. If we assume the while loop runs for a very long time, the application would run out of memory and crash.

My question: is this true? If so, what to do to avoid it?

Tim S.
  • 13,597
  • 7
  • 46
  • 72
  • 1
    http://stackoverflow.com/a/2423293/798818 – Mob Jul 13 '12 at 12:39
  • 2
    *In all languages I know, garbage (if the language has any) is collected when a method ends.* Point one language! You mistake garbage collection w/ automatic reference counting and C++ alike destructors of stack allocated object. Java allocates no objects on the stack *(by design, but it's technically possible by EA [escape analysis] or ED[escape detection])* so the statement is incorrect at best (very wrong at worst) – bestsss Jul 13 '12 at 12:53

5 Answers5

7

First, in Java GC is non-deterministic. When the object is no longer referenced, it is suitable to be collected in the next GC run, but it is not mandated. Even calling System.gc() is just a suggestion to the GC system.

Second, what counts is references. In each instance of the loop, you overwrite the reference to the thread object. If the threads have finished, there is no need to exit the method to have them collected (of course, while the threads are running they won't be collected, even if your code has no references to it). The issue of exiting the method where the object was created is not relevant.

SJuan76
  • 24,532
  • 6
  • 47
  • 87
  • so because I'm overwriting the reference, the thread is not reachable and thus garbage collected when it's finished running, yes? – Tim S. Jul 13 '12 at 12:45
  • "when it's finished running" nothing special happens except when the thread finishes running. The GC can run at any time. – Peter Lawrey Jul 13 '12 at 12:49
4

The GC runs when it is needed (e.g. when you try to allocate memory and the eden space is full)

This can happen on any line of code where you allocate memory (in any thread) This means even if you don't allocate memory in one thread a GC can still occur because memory was allocated in another thread.

You can also trigger a GC explicitly or using a JMX tool like visualvm.

In short: a GC can occur at any time.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    a true concurrent GC can run at any time, or even all the time (the latter needs read-barriers though) – bestsss Jul 13 '12 at 12:45
1

Every instance of MyThread will be marked to be collected by GC right after start of the another loop iteration. If You want to run MyThread as a Thread You need to use the start() method!

In a case when You are using start() method the MyThread will be marked to be collected by GC right after start of the another loop iteration and! the end of run() method.

But there is no guaranties about when it will be collected by the GC. This is a GC specific thing.

Galdrian
  • 11
  • 1
0

It is granted that it will be called on the thread after than it finish the job and dont use more the data, but not when, because the garbage collector is automatically called by the virtual machine periodically or when some events occur.

So from when the thread has been terminated and data become unused you cannot know if the dat have been auto collected or not.

You can also call it explicitely with: System.gc().

If your thread were terminated and his pointed data is not more used, after the explicit call it is granted that it has been collected.

Luca C.
  • 11,714
  • 1
  • 86
  • 77
0

In the code you've posted above, no Thread is actually being executed in parallel. To spawn a new thread, you need to have called the .start() method which internally calls the .run() method for the Thread. Right now, everything is running sequentially. So your thread.run() will finish its execution, your current thread will sleep, and your while will continue its loop and do it over and over.

The GC can hit at any point and, as others have stated, running threads (threads that were started with start()) will only be GCed if they have finished their execution.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724