I know use System.exit(0) can end a java program, for instance, if I have a JFrame window, it will close and end the program, but I wonder how many other ways, can it be closed and the program be ended ? Including when an error occurs, will the program be shut down and the JFrame be closed ?
To add to other answers:
If the process that is hosting the VM is forcefully terminated, your program will spontaneously disappear
The same happens if the plug gets pulled on the machine hosting the VM :)
A Java program ends when the last Thread without daemon flag ends, or when you call a method that shuts down the virtual machine (System.exit(), Runtime.exit(), Runtime.halt() and possibly a few more).
Anything else is up to libraries that call System.exit() (such as a JFrame with EXIT_ON_CLOSE).
Here's all I can think of off the top of my head:
main() returns (either a value or a void() main finishes executing its last statement)
program throws an exception uncaught
System.exit(int)
It can crash?
In your case of a JFrame closing, I believe there would be an onClose() handler which either calls System.exit(0) or causes the main method to return.
One other way the Java program ends is when the last statement in the java code is executed.
Also when java.lang.OutOfMemory error occurs, the program terminates abnormally. This occurs 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.
I've answered your question in the context of Swing GUIs given your mentioning of JFrame.
With a Swing GUI the Event Dispatch thread will log any exceptions that occur but will not terminate the application in this situation.
Similarly, if another thread throws an exception and terminates the Event Dispatch thread will ensure that the application is kept alive (as it is not a daemon thread).
One final point: If you wish your application to be terminated when a JFrame is closed, you need to call: setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
Otherwise the frame will simply be hidden when you close it, but the application will continue to run.
You can end a running Java program externally. By killing the java.exe process from task manager (in case of windows)
You can use Application.exit() as well.
Related
This question already has answers here:
Do java threads get deleted when they finish
(3 answers)
Closed 7 years ago.
I want to know if a thread in java closes itself when run method ends.
I mean, I have a new thread declaration:
new Thread(new SubmitDataOnBackground(handler.getIDValue(), data, this.context)).start();
And then, in SubmitDataOnBackground I have this run method:
public void run() {
SubmitDataHandler submit = new SubmitDataHandler(ID, data, this.context);
submit.buildAndSubmitData();
}
After buildandSubmitData finishes, does the thread close itself or I have to add any code somewhere?
I am not sure if I am leaving a new thread opened each time I call this method or it is ok.
My application is a server so it will never ends because it is active the whole time. I just want to know the amount of threads is not outnumbered because it just creates new ones without closing the others when finish.
Threads close themselves after the run method has been called. Read this for further information https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html
EDIT: If you want to avoid this behaviour, I recommend using ThreadPools.
Yes, a thread finishes when run() method execution ends. You can read more on threads and concurency in general here
One tip here - when using multiple threads that are started and finished all the time, it is a good idea to use a thread pool. That is because creating a thread is quite a heavy operation.
Threads are terminated after finishing their jobs (when the execution of run() ends). If you want to check, use isAlive().
Yes, threads are terminated after finishing their specified jobs (sequence of instructions) in run() method.
However, the thread object that has been created still exists, allowing you call it again with Thread.start() to create a new Thread.
If you want to be sure that your thread run method ends before continuing doing something more, try to use the method Thread.join() in the same place where you are working with threads.
Read this for further information about that:
https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join%28%29
In order to actually make a Thread stop itself, the process is quite simple. All you need to do is simply let the run method run out and return.
public void run(){
// implement your code
// Just about to return and the Thread will then stop soon after
}
Note that the thread will not necessarily be declared finished immediately after the run method has finished, as the Java Virtual Machine (JVM) still needs to finish it off in the background, but it should terminate completely soon after.
In other words, when a normal Thread (also referred to as a user Thread) is created, it is expected that it will complete its work and not shut down permanetly. The JVM will not terminate until all user Threads have finished, or until a call is made to the System.exit() method, which terminates the JVM abruptly.
EDIT: System.exit() does not stop the JVM abruptly, it executes all the shutdown hooks first. Runtime.getRuntime().halt() stops the JVM without any further processing.
In a situation where a fatal exception occurs, it can be assumed that the program is no longer in a safe state to run and should be terminated as soon as possible. However, I would like to inform the user what fatal error has occurred without requiring them to go searching through log files. Is the best solution to terminate all other executing Threads, only leaving the current thread alive for calling up a JDialog?
This was my attempt at the solution:
public void killAlienThreads() {
Thread[] threads;
while ((threads = Thread.getAllStackTraces().keySet().toArray(new Thread[0])).length != 1) {
for (Thread thread : threads) {
if (thread != Thread.currentThread())
thread.stop();
}
}
}
After this method is called, the current thread goes on to alert the user of the issue, and then close off the program once the remaining dialog is disposed.
There are many issues with this code. For one, new threads could be created while attempting to shut down all of them, this requires a loop that only breaks when it knows only the current thread is left. Also, as Eclipse warns me, Thread.stop() is deprecated, however Thread.interrupt() is not guaranteed to immediately stop a thread. Regardless, instead of terminating all other threads, this method simply gives me a barrage of InterruptedExceptions.
So, how can a program in an "unsafe state" be safely terminated while still allowing for an error dialog to inform the user?
EDIT:
Let me explain a couple things to make my question more clear. When I say "fatal exception" I mean a checked Exception (not an Error) that my program has caught and does not know how to deal with. When one of these errors occurs it can be assumed that the program is no longer in a functional state (or it is "unsafe") and should be terminated as soon as possible. However, waiting for the user to click the "OK" button on an error dialog can take an indefinite amount of time. So, I wish to terminate the program immediately when a "fatal exception occurs" without having to wait for the user to acknowledge the error dialog and close it.
While throwing a proper exception generally leave a lot of objects in a valid state, calling an unsafe method like Thead.stop() can completely corrupt important state and cause even more bad side effects.
The safest way is to let the main process die as quickly as possible and use another daemon process to report the error.
If you have to do it from within the JVM, you'll probably have to look at debugging or instrumentation APIs as it is not possible to interrupt a thread that does not call interruptable methods.
I have a call to System.exit(1) in my multi-threaded program. However from time to time instead of return code 1, the program exits with return code 0. I don't have any other calls System.exit() and I'm positive that the program doesn't exit cleanly. What can be the cause, and how can I avoid it?
Note that the error is intermittent and I cannot reproduce the same behavior in single threaded programs.
Modify your design to execute a more controlled shutdown.
There should be no expectation that calling System.exit() in an application with multiple threads would ever cause the program to exit cleanly.
Rather than calling System.exit() to leave the program, you should send shutdown messages to each moving component and use Thread.join() to recover any threads you created. Your application should be able to shut down all pieces nicely this way. The final command in the main thread should be to return your exit code. If you just call System.exit(), you're leaving all of these shut down details to the JVM, which is just going to take a heavy-handed approach and kill everything on the spot.
Have you used Runtime.getRuntime.addShutdownHook() at all? A call to System.exit() will invoke any shutdown hooks that may be installed and this could be changing the exit code.
The documentation for Runtime.halt(int) says the following about its argument:
If the exit (equivalently, System.exit) method has already been invoked then this status code will override the status code passed to that method.
So perhaps something is invoking Runtime.halt(int). In a shutdown hook or finalizer?
I think the only way this may happen if your JVM terminates before System.exit(1) actually executed. Do you think this may be possible in your system?
Either, the code with System.exit(1) is being executed in a daemon thread, and so when all other live (non-daemon) threads finish working JVM exits cleanly (or not cleanly, as you can still get 0 exit code if you program throws an exception!)
Alternatively, as #Erick Robertson suggested, maybe something is modifying the exit status from a hook or something, although I am not sure how this is possible.
Note: please disregard my previous comment. Calling System.exit(1) will terminate all currently running daemon/non-daemon threads all-together.
Up to now I used my application as a stand alone product. So, when user pressed "Stop" button I called System.exit(0); and it was fine.
Now my application will be called (in a programmatic way) from another program. So, I afraid that System.exit(0); will kill not only my process but also the external software which started my program.
So, what is the correct way to shutdown my application if a corresponding request from an external software is received? My application is an GUI application. So, I want to close the window but I also want to close all processes performed by my program.
ADDED:
To be more specific, I want to close all threads started by my program. My program does not start any OS process or any other program.
If the threads you've launched are still processing then calling System.exit(0) will cause them to be killed. In some cases, this can leave your application in an inconsistent state. Imagine that the thread was saving a file for example.
You should ensure that the your threads are all 'happy' to die before calling System.exit.
One technique you can use for this with long running threads is poisoning. To do this you send the threads a message that they should now die gracefully - i.e. a poson message. Once they have all died, it is safe to call System.exit(0) to terminate the Swing event handling thread.
There a loads of different ways of implementing poisoning, you could just set a global flag variable that the threads check to see if they've been poisoned, or you could use the Java 5 threading libraries. Take a look at this Javadoc for example and you'll find references to this technique:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html
As long as your programm isn't sharing an application server with others, shuting down the VM by calling System.exit(0) terminates all threads.
From Javadoc
System.exit Terminates the currently running Java Virtual Machine)
EDIT:
If you want to do some clean up code before shutdown, http://java.sun.com/j2se/1.4.2/docs/guide/lang/hook-design.html
There is on "one-size-fits-all" answer to this that's a drop-in replacement for System.exit, unfortunately.
You will generally need to set some kind of flag that signals to all of your threads that it is time to exit, and ensure that they check this flag regularly. This will let them clean up gracefully without stopping abruptly, and it also ensures the effects are limited to your own components. In this case your application's main thread would also observe the flag, wait for all the "worker" type threads to finish and would then return all the way up the stack until your application's entry point was reached.
This question is not too dissimilar to the deprecated Thread.stop (etc) methods, especially with regards to replacing System.exit with something more respectful. In that light, the why is Thread.stop() deprecated page may be useful reading.
Throwing an exception (a custom one called something like ApplicationStopException) to unwind the stack of the main thread is not such a bad idea; this prevents you from having to handle the special logic all over your code and instead lets the "message" propagate to the higher levels, where they can take whatever action is needed to exit your program gracefully.
I recommend you to do flagging to stop the thread so that the thread will know when it has to stop. For GUI and window, you can call frame.dispose().
For System.exit(), I think it will not affect the caller, you may try to see what is the real effect but as other people already recommended, do not call it directly like that, just let the threads stop by itself
I have a Java program which is being started via ProcessBuilder from another Java program.
System.exit(0) is called from the child program, but for some of our users (on Windows) the java.exe process associated with the child doesn't terminate. The child program has no shutdown hooks, nor does it have a SecurityManager which might stop System.exit() from terminating the VM. I can't reproduce the problem myself on Linux or Windows Vista. So far, the only reports of the problem come from two Windows XP users and one Vista user, using two different JREs (1.6.0_15 and 1.6.0_18), but they're able to reproduce the problem every time.
Can anyone suggest reasons why the JVM would fail to terminate after System.exit(), and then only on some machines?
Edit 1: I got the user to install the JDK so we could get a thread dump from the offending VM. What the user told me is that the VM process disappears from VisualVM as soon as he clicks on the 'Quit' item in my menu---but, according to Windows Task Manager, the process hasn't terminated, and no matter how long the user waits (minutes, hours), it never terminates.
Edit 2: I have confirmed now that Process.waitFor() in the parent program never returns for at least one of the users having the problem. So, to summarize: The child VM seems to be dead (VisualVM doesn't even see it) but the parent still sees the process as live and so does Windows.
This can happen if your code (or a library you use) has a shutdown hook or a finalizer that doesn't finish cleanly.
A more vigorous (so should only be used in extreme cases!) way to force shutdown is by running:
Runtime.getRuntime().halt(0);
The parent process has one thread
dedicated to consuming each of the
child's STDOUT and STDERR (which
passes that output through to a log
file). So far as I can see, those are
working properly, since we're seeing
all the output we expect to see in the
log
i had a similar problem with my program not disappearing from task mgr when i was consuming the stdout/stderr. in my case, if I closed the stream that was listening before calling system.exit() then the javaw.exe hung around. strange, it wasn't writing to the stream...
the solution in my case was to simply flush the stream rather than close it before existing. of course, you could always flush and then redirect back to stdout and stderr before exit.
Check if there is a deadlock.
For example,
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
System.exit(1);
and in the close()
public void close() {
// some code
System.exit(1);
}
The System.exit() actually calls the shutdown hook and finalizers. So, if your shutdown hook calls the exit() again internally, for some reason (for example, when the close() raises an exception for which you want to exit the program, then you will call exit() there also). Like this..
public void close() {
try {
// some code that raises exception which requires to exit the program
} catch(Exception exceptionWhichWhenOccurredShouldExitProgram) {
log.error(exceptionWhichWhenOccurredShouldExitProgram);
System.exit(1);
}
}
Though, it is a good practice to throw the exception, some may choose to log and exit.
Note, also, that Ctrl+C will also not work if there is a deadlock.
Since it also calls the shutdown hook.
Anyways, if it is the case, the problem can be solved by this workaround:
private static AtomicBoolean exitCalled=new AtomicBoolean();
private static void exit(int status) {
if(!exitCalled.get()) {
exitCalled.set(true);
System.exit(status);
}
}
Runtime.getRuntime().addShutdownHook(new Thread(MyClass::close));
exit(1);
}
private static void close() {
exit(1);
}
P.S: I feel that the above exit() version must actually be written
in the System.exit() method only (may be some PR for JDK?) Because,
there is practically no point (at least from what I see) in
entertaining a deadlock in System.exit()
Here are a couple of scenarios...
Per the definition of a Thread in http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Thread.html
...
When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class). The Java Virtual Machine continues to execute threads until either of the following occurs:
1) The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
2) All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.
Another possibility is if the method runFinalizersOnExit has been called. as per the documentation in http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html
Deprecated. This method is inherently unsafe. It may result in finalizers being called on live objects while other threads are concurrently manipulating those objects, resulting in erratic behavior or deadlock.
Enable or disable finalization on exit; doing so specifies that the finalizers of all objects that have finalizers that have not yet been automatically invoked are to be run before the Java runtime exits. By default, finalization on exit is disabled.
If there is a security manager, its checkExit method is first called with 0 as its argument to ensure the exit is allowed. This could result in a SecurityException.
Maybe a badly written finalizer? A shutdown hook was my first thought when I read the subject line. Speculation: would a thread that catches InterruptedException and keeps on running anyway hold up the exit process?
It seems to me that if the problem is reproducible, you should be able to attach to the JVM and get a thread list/stack trace that shows what is hung up.
Are you sure that the child is still really running and that it's not just an unreaped zombie process?
Does the parent process consumes the error- and outputstream from the child process?
If under some OS the childprocess print out some errors/warning on stdout/stderr and the parent process is not consuming the streams, the childprocess will block and not reach System.exit();
Hy i had the same problem, but the couse for me was i was using the remote Debugging(VmArgs: -Xdebug -Xrunjdwp:transport=dt_socket,address=%port%,server=y,suspend=y) when i disabled this the java.exe Process exited as expected.
I think all of the obvious causes have been provisionally covered; e.g. finalizers, shutdown hooks, not correctly draining standard output / standard error in the parent process. You now need more evidence to figure what is going on.
Suggestions:
Set up a Windows XP or Vista machine (or virtual), install the relevant JRE and your app, and try to reproduce the problem. Once you can reproduce the problem, either attach a debugger or send the relevant signal to get a thread dump to standard error.
If you cannot reproduce the problem as above, get one of your users to take a thread dump, and forward you the log file.
Another case not mentioned here is if the shutdown hooks hang on something so be careful in writing the shutdown hook code(and if a 3rd party library registered a shutdown hook that is hanging as well).
Dean