Do Java Threads need any cleanup? - java

I see that all the stop and destroy and anything else that deals with cleanup methods have been deprecated.
If I have a new Thread() or a class that extends Thread running, do I need to do anything in its run() method other than let it get to the end of regular execution? Or is there a background mechanism that understands that the Thread has run through all its tasks and can be destroyed?

When you call start() on your thread, native mechanism in JVM close to the operating system are starting your thread, eventually executing run(). When run() finishes, JVM takes care of everything.
You might be concerned about garbage collection or other resources cleanup. Of course if you open file/network connection inside a thread, it must be closed like everywhere else. Also the garbage collector, while analyzing live objects, takes into account objects referred from running threads. But the moment thread finishes, all the objects referenced by it (or by Runnable implementation passed to the thread) are eligible for garbage collection.
quick&dirty edit for exit method of Thread, as visible contextClassLoader is missing x.x
private void exit() {
if (group != null) {
group.remove(this);
group = null;
}
/* Aggressively null out all reference fields: see bug 4006245 */
target = null;
/* Speed the release of some of these resources */
threadLocals = null;
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}

No cleanup needed. Once it finishes its task, the jvm will kill it.

The stop() method actually causes the Thread to throw an Error or Exception. The reason it is deprecated is this can happen anywhere in the code anything it modifies in a potentially unknown state. stop() is only really safe when stopping the current thread because you know when it will happen. BTW, You can catch the Error/Exception which would mean the Thread does not stop().
In any case, the result is the same, the run() returns (or fails to catch an Exception/Error). The stop() method triggers a special Error called ThreadDeath. The only thing special about it is that normally, an uncaught exception/error is printed, but this one is not. (And it doesn't have Error at the end of its name ;) You can change this behaviour if you wish.
When the Thread is no longer referenced, it can be cleaned up. (just like any other object) Note: you can hold a reference to it in another thread, preventing it from being cleaned up even thought it has finished.

Related

Does JVM garbage collector run when application shuts down?

I'm extremely confused about how finalizers work in the JVM regarding Garbage Collection from several sources here and around the internet.
It is my understanding, the usual approach is not to rely on finalizers to perform clean up as there's no guarantee about when they will be called or whether they would be called at all if the application finishes. However, I would still expect them to be called when the application finishes and all object cease to exist, as long as the application is alive.
In my particular case, I have an application with a class that opens a connection to another resource.
Simplified we will have
public class MyClass {
Connection connection = new Connection();
public MyClass() {
connection.open();
}
public void close() {
connection.close();
}
#Override
protected void finalize() {
connection.close();
}
}
public class Main {
public static void main(String[] args) {
MyClass instance = new MyClass();
// If I call instance.close(), application ends when it reaches end of main method
// instance.close()
// If not called, application will not end.
}
}
Note the encapsulation purpose of "MyClass", the calling code does not necessarily need to know (nor does it need to) that he's using a non managed resource.
What happens is the application keeps running for ever, I assume hanged up on the open connection without ever releasing it since GC isn't called (and will never be called since there's no real memory pressure).
If the GC is not called when the application finishes, is there a way to guarantee the non managed resource (the connection) is closed when the application finishes? Obviously without having to explicitly call close.
I've seen the AutoClosable interface, and that is definitively an option but it still doesn't guarantee the connection will be eventually dropped when the application finishes.
If the GC is not called when the application finishes, is there a way to guarantee the non managed resource (the connection) is closed when the application finishes? Obviously without having to explicitly call close.
If you call (on Unix)
kill -9 {pid}
the process dies immediately without notifying the process. e.g no finally blocks are called. There is nothing you can do to prevent this.
You can enable to that finalizers are called on a graceful shutdown with runFinalizersOnExit but only on a graceful shutdown.
BTW If you pull out the power, or the network connection you won't have a graceful disconnect either, so you can't avoid needing to handle this, all you can do is cleanup on a graceful close()/shutdown.

java thread - why stopping a new thread is allowed

I have a question for the below statements
When a thread is a new thread, it is merely an empty Thread object. No
system resources have been allocated for it yet. When a thread is in
this state, you can only start the thread or stop it. Calling any
method besides start or stop when a thread is in this state makes no
sense and causes an IllegalThreadStateException.
Why does java allow to stop a thread which is not even started... in which scenario one will have to invoke stop() and a new thread?
First of all do no use the function which have been marked as deprecated.
As the documentation indicates for Stop,
It is permitted to stop a thread that has not yet been started. If the thread is eventually started, it immediately terminates.
Moreover, if I look at the code for Stop which is
#Deprecated
public final void stop() {
// If the thread is already dead, return.
// A zero status value corresponds to "NEW".
if ((threadStatus != 0) && !isAlive()) {
return;
}
stop1(new ThreadDeath());
}
As you can see from code it is designed such that, it returns normally when threadStatus != 0 (A zero status value corresponds to state "NEW") or if the thread is already stopped.
Other answers address the specifics, so I'll try talking about the more general idea behind it.
Essentially, if designers don't allow methods being called, they are trying to detect programming errors. In the designers view, interrupt() being called when the thread was never started seemed likely to be a bug, whereas the same for stop() seemed less so.
There are other similar examples, too. For example, Future#cancel() can be called multiple times.
Ultimately I think there is an element of subjectivity/preference, even though in some cases one makes clearly more sense than the other.

Thread keeping a reference forever

I have a class:
class RenderView implements Runnable {
Thread renderThread;
public void run() {
while(!Thread.currentThread().isInterrupted()) {
//does some work
}
}
//At some point in executed code, inside RenderView class (i'm sure it's executed)
renderThread = new Thread (this);
//When activity is closed (also, i'm sure this part is executed)
renderThread.interrupt();
And the renderThread really stops (at least, the run() method quits).
But for some reason, there is still some reference to renderView in my code, after i exit the activity. This is causing me a huge memory leak.
And a hprof dump tells me:
java.lang.Thread (this one is in GC Root)
has a reference to
target (mypackage.RenderView)
I have no idea why this Thread class is keeping a reference to my Thread, even though i've already finished the Thread! Any ideas?
EDIT: The renderView is referenced in, say, Activity B. So, when i exit the activity, no reference to renderThread should still be reachable. But still i tried setting renderThread = null : doesn't work. As i was able to find out via MAT Analyzer, the only thing that keeps renderView from being Garbage Collected is this weir reference from java.lang.Thread.
Why don't you just use an AsyncTask or runOnUIThread()?
I've never seen a need for what your doing. Perhaps there is one but otherwise just use AsyncTask or runOnUIThread. Don't reinvent the wheel.
Release your thread instance with
renderThread = null;
A thread instance is as any other instance, an object. Even if it finished running, you keep the reference to it, until you release it.
did you try to nullify renderThread?
Actually, renderThread.interrupt may not stop the thread, it is just setting a flag and singnals JVM that it can be interrupted.That is why may be your thread is still running.The best practice is gracefully exit from run method by just setting a flag in the while loop.
while(isRunning){
}
// at some point, say
isRunning = false;
The best practices on Android UI design can be had from the following link.
Android UI design pattern:

is there any way to confirm if the thread is killed at the end of execution?

is there any way to confirm if the thread is killed at the end of execution? If the garbage collector takes long time to destroy the threads even when they are available for GC, out of memory exceptions may arise. to get rid of those kind of issues, it would be good to know if the threads have been destroyed.
As of now, my understanding is that at the end of run method , the thread gets killed and we need not do anything explicitly to kill the thread instance.
Thanks in advance!
class A
{
public static void main()
{
Thread t = new Thread(new TestA());
t.start();
Thread t1 = new Thread(new TestB());
t1.start();
Thread t2 = new Thread(new TestC());
t2.start();
}
}
class TestA implements Runnable {
Thread t;
public void run() {
for(...){
try{
}catch()
{
....
}
}
}
}
You are absolutely right that "at the end of run method, the thread gets killed and we need not do anything explicitly to kill the thread instance". Simply letting the thread leave its run() method normally is enough.
If you want to make sure that a particular thread has terminated, then Thread.isAlive() will check, and Thread.join() will wait until it happens. If you have a particular set of threads that you're worried about, then keep a reference to them somewhere, and check up on them using these methods.
Thread.getAllStackTraces()
gets you a current map of threads/stacktraces. However I would normally expect the JVM to clear up the threads upon exit from run(). Obviously if you're using some sort of thread pooling then that's not the case.
You can use some softwares like visualvm to monitor the thread states .
These kind of softwares will give you full flexibility to profile your application in a visual way.
To check the state of a thread , you can call the getState() method on a thread object to see the state of the thread.
The javadoc of OutOfMemoryError says:
Thrown when the Java Virtual Machine cannot allocate an object because
it is out of memory, and no more memory could be made available by the
garbage collector.
So, if a thread is not running anymore and is eligible to GC, the GC will try to collect it before throwing an OOM. Like with any other object.
is there any way to confirm if the thread is killed at the end of execution?
There's no sense confirming something you know to be true. Whenever the JVM process dies, all its threads are automatically killed by the operating system. Any other behavior is a bug in the OS.
If the garbage collector takes long time to destroy the threads even when they are available for GC, out of memory exceptions may arise.
The garbage collector doesn't kill threads - the JVM wraps operating-system-specific thread libraries into a consistent Java-language thread abstraction, so those thread libraries determine when a thread dies.
my understanding is that at the end of run method, the thread gets killed and we need not do anything explicitly to kill the thread instance.
That is correct.
If you look up in the javadoc for the Thread class you will see many methods that might help you check what you want, for example:
activeCount() : Returns the number of active threads in the current thread's thread group.
You can use this as a debug method.
isAlive() : Tests if this thread is alive.
To check if a specific thread is alive.
join() : Waits for this thread to die.
If you call this at the end of your method then it will wait for the thread to join (i.e. to end execution) before advancing. If you call for all threads, then you are sure that all have finished when the main() has finished.
destroy() : Destroys this thread, without any cleanup.
Does what it says, but I would never suggest this.
Hope it helps!

Killing a thread with a complex subroutine. Java

As many others I have a problem killing my thread without using stop().
I have tried to use volatile on a variable with a while loop in my threads run() routine.
The problem is as far as I can see, that the while loop only checks the variable before every turn. The complex routine Im running takes a long time, and because of that the thread is not terminated immediately.
The thread I want to terminate is a routine that connects to another server and it uses a looooong time. And I want to have an abort button for this. (Terminating the thread). I'll try to explane with some code.
class MyConnectClass{
Thread conThread;
volitile boolean threadTerminator = false;
..some code with connect and abort button..
public void actionPerformed(ActionEvent e) {
String btnName = e.getActionCommand();
if(btnName.equalsIgnoreCase("terminate")){
threadTerminator = true;
conThread.interrupt();
System.out.println("#INFO# USER ABORTED CURRENT OPERATION!");
}else if(btnName.equalsIgnoreCase("connectToServer")){
conThread = new Thread() {
public void run() {
while(threadTerminator == false){
doComplexConnect(); //Uses a loooong time
}
}
}
conThread.start();
}
}
}
How can I kill my "connection" thread instantly?
Thanks.
Java abandoned the stop() approach in Threads a while back because killing a Thread ungracefully caused huge problems in the JVM. From the Javadoc for stop():
Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait.
In most cases, it is up to you to check the threadTerminator var whenever it is safe for you to terminate, and handle the thread exit gracefully. See http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
If you are doing long I/O, you may be in trouble. Some I/O operations throw an InterruptedException, in which case, you can interrupt the thread, and, if you were in that I/O, that exception will be thrown more or less instantly, and you can abort and cleanup the thread. For this reason, interrupting a thread is preferable to using a special custom threadTerminator variable - it's much more standard. In you main code outside of the I/O, check for interrupted() or isInterrupted() periodically (instead of threadTerminator == false).
If you are doing I/O that doesn't throw InterruptedException, sometimes you can close the Socket or similar, and catch the IOException. And sometimes you are stuck.
Why don't you interrupt the thread and just move on, letting it hang until it finishes? The user could initiate a different action (thread) while the old thread finishes gracefully (which, from what I see you are pretty much doing already btw)
The downside of this that you have trouble when the user starts clicking "connectToServer" a lot (many threads), or when the threads fail to terminate (hanged threads). But maybe it's sufficient for your purpose?
Edit:
It would be simple to implement a mechanism that prevents spawning a new conthread unless "it's good to go" (e.g., use a semaphore).
The tricky part will be deciding whether it's good to open a new connection. You could ask the original thread (I.e. have a isalive() method), or the party you are trying to connect to. Or you could go for a timeout solution. For example, you could let conthread update a timestamp and decide it's dead if the timestamp isn't updated for 1 min etc. The most generally applicable solution would probably be the timeout solution.

Categories