198

In Java, What is the difference with or without System.exit(0) in following code?

public class TestExit
{      
    public static void main(String[] args)
    { 
        System.out.println("hello world");

        System.exit(0);  // is it necessary? And when it must be called? 
    }      
}

The document says: "This method never returns normally." What does it mean?

Community
  • 1
  • 1
pierrotlefou
  • 39,805
  • 37
  • 135
  • 175
  • See also https://stackoverflow.com/questions/28738307/how-exactly-works-the-java-application-exit-code-of-the-main-method – Roland Jul 07 '22 at 08:44

10 Answers10

217

System.exit() can be used to run shutdown hooks before the program quits. This is a convenient way to handle shutdown in bigger programs, where all parts of the program can't (and shouldn't) be aware of each other. Then, if someone wants to quit, he can simply call System.exit(), and the shutdown hooks (if properly set up) take care of doing all necessary shutdown ceremonies such as closing files, releasing resources etc.

"This method never returns normally." means just that the method won't return; once a thread goes there, it won't come back.

Another, maybe more common, way to quit a program is to simply to reach the end of the main method. But if there are any non-daemon threads running, they will not be shut down and thus the JVM will not exit. Thus, if you have any such non-daemon threads, you need some other means (than the shutdown hooks) to shut down all non-daemon threads and release other resources. If there are no other non-daemon threads, returning from main will shut down the JVM and will call the shutdown hooks.

For some reason shutdown hooks seem to be an undervalued and misunderstood mechanism, and people are reinventing the wheel with all kind of proprietary custom hacks to quit their programs. I would encourage using shutdown hooks; it's all there in the standard Runtime that you'll be using anyway.

GreenGiant
  • 4,930
  • 1
  • 46
  • 76
Joonas Pulakka
  • 36,252
  • 29
  • 106
  • 169
  • 11
    "This method never returns normally." means just that the method won't return; once a thread goes there, it won't come back. Note in particular that this means you can't unit test a method that makes a System.exit(0) call... – Bill Michell Sep 15 '10 at 10:05
  • 6
    -1 Incorrect. Shutdown hooks will run if the JVM terminates normally, no matter if it's because of System.exit or termination of main(). See http://zx81/doku/java/javadoc/j2se1.5.0/docs/api/java/lang/Runtime.html#addShutdownHook%28java.lang.Thread%29 – sleske Sep 15 '10 at 10:12
  • 31
    @sleske: Termination of main() is not sufficient if there are other non-daemon threads around. Shutdown is initiated only after the last non-daemon thread has terminated, unless you explicitly call System.exit(). That's clearly stated in the Runtime documentation. – Joonas Pulakka Sep 15 '10 at 10:30
  • 3
    Note that if your shutdown hook in turn relies on the thread that called System.exit, you will deadlock. – djechlin Nov 06 '13 at 21:32
  • 8
    Something to add on, if someone halts a runtime, shutdown hooks will not run (`Runtime.getRuntime().halt()`) – Rogue Dec 18 '13 at 00:03
  • As mentioned [here](http://stackoverflow.com/a/512660/4163002), shutdown hooks will get cut off by the OS and aren't a very full-proof way of preventing shutdown, even on Windows. They also do not work [when using javaw](http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4486580). – ZX9 Mar 22 '16 at 15:32
  • 1
    @ZX9: Yes, if you kill -9 a process, then shutdown hooks obviously won't run. Regarding javaw, that seems to be some old bug, reported 15 years ago against Java 1.3. I'm quite certain that shutdown hooks work fine with this decade's Java, no matter whether you use java.exe, javaw.exe, or Invocation API to launch your process. – Joonas Pulakka Mar 22 '16 at 18:49
  • 1
    @JoonasPulakka I'd never had the javaw issue myself, actually, so I apologize for pervading that; thanks for clarification! Regarding the OS kill, I'm not sure if it's the JVM or OS, but I've definitely had issues with shutdown hooks not being given enough time to finish, even with a thread that I didn't think was computation-heavy. – ZX9 Mar 23 '16 at 15:13
  • 2
    I colleague of mine once showed me a trick to make sure that `System.exit()` would throw some security exception rather than exiting Java. Don’t remember what it was, but it allowed him to unit test a method that might call `System.exit()`. Still a case for not overusing `System.exit()`, I should think. – Ole V.V. Sep 09 '16 at 05:27
49

In that case, it's not needed. No extra threads will have been started up, you're not changing the exit code (which defaults to 0) - basically it's pointless.

When the docs say the method never returns normally, it means the subsequent line of code is effectively unreachable, even though the compiler doesn't know that:

System.exit(0);
System.out.println("This line will never be reached");

Either an exception will be thrown, or the VM will terminate before returning. It will never "just return".

It's very rare to be worth calling System.exit() IME. It can make sense if you're writing a command line tool, and you want to indicate an error via the exit code rather than just throwing an exception... but I can't remember the last time I used it in normal production code.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    Why doesn't the compiler know that? Isn't System.exit() special enough to warrant specific detection code? – Bart van Heukelom Sep 15 '10 at 08:50
  • 5
    @Bart: No, I don't think so. Putting special cases in the language for things like this adds to language complexity with very little benefit. – Jon Skeet Sep 15 '10 at 08:56
  • I thought "never returns normally" had to do with "abrupt completion" of the statement. (JLS section 14.1). Am I wrong? – aioobe Sep 15 '10 at 08:59
  • @aioobe: No, you're right. `System.exit()` will never complete normally - it will always either complete with an exception, or with the VM shutting down (which isn't really covered in the JLS). – Jon Skeet Sep 15 '10 at 09:14
  • Okay nicely explained but does JVM also calls it anytime? if not then why they've provided parameterized exit method? I mean user will always provide 0 instead of other options i.e 1 to 255 – Govinda Sakhare Mar 20 '16 at 12:18
  • 1
    @piechuckerr: What makes you think that? It's entirely reasonable to call it with a value other than 0, to indicate to the calling shell (or whatever) that the program has encountered an error. – Jon Skeet Mar 20 '16 at 14:04
  • The Only thing I want to know is does JVM calls it internally in any scenario? – Govinda Sakhare Mar 20 '16 at 17:26
  • @piechuckerr: No idea... What effect are you interested in? – Jon Skeet Mar 20 '16 at 17:27
  • When to pass the non-zero value? any scenario? so far whatever code I've seen everyone passing value 0. – Govinda Sakhare Mar 20 '16 at 17:29
  • @piechuckerr: As I said before, it's usually to indicate that the program has encountered an error. – Jon Skeet Mar 20 '16 at 17:41
15

The method never returns because it's the end of the world and none of your code is going to be executed next.

Your application, in your example, would exit anyway at the same spot in the code, but, if you use System.exit. you have the option of returning a custom code to the enviroment, like, say

System.exit(42);

Who is going to make use of your exit code? A script that called the application. Works in Windows, Unix and all other scriptable environments.

Why return a code? To say things like "I did not succeed", "The database did not answer".

To see how to get the value od an exit code and use it in a unix shell script or windows cmd script, you might check this answer on this site

Community
  • 1
  • 1
mico
  • 1,816
  • 1
  • 18
  • 27
  • Better explanation: https://stackoverflow.com/questions/28738307/how-exactly-works-the-java-application-exit-code-of-the-main-method – Roland Jul 07 '22 at 08:43
13

System.exit(0) terminates the JVM. In simple examples like this it is difficult to percieve the difference. The parameter is passed back to the OS and is normally used to indicate abnormal termination (eg some kind of fatal error), so if you called java from a batch file or shell script you'd be able to get this value and get an idea if the application was successful.

It would make a quite an impact if you called System.exit(0) on an application deployed to an application server (think about it before you try it).

Qwerky
  • 18,217
  • 6
  • 44
  • 80
12

In applications that may have complex shutdown hooks, this method should not be called from an unknown thread. System.exit never exits normally because the call will block until the JVM is terminated. It's as if whatever code is running that has the power plug pulled on it before it can finish. Calling System.exit will initiate the program's shutdown hooks and whatever thread that calls System.exit will block until program termination. This has the implication that if the shutdown hook in turn submits a task to the thread from which System.exit was called, the program will deadlock.

I'm handling this in my code with the following:

public static void exit(final int status) {
    new Thread("App-exit") {
        @Override
        public void run() {
            System.exit(status);
        }
    }.start();
}
djechlin
  • 59,258
  • 35
  • 162
  • 290
  • I also had the issue where System.exit would not actually end the JVM. It only happend under certain conditions though. A threadump I took didn't gave me any insights about which threads / shutdown handlers are blocking the shutdown. Using the code described in the comment helped me to solve it! – Kai Oct 02 '17 at 08:52
8

One should NEVER call System.exit(0) for these reasons:

  1. It is a hidden "goto" and "gotos" break the control flow. Relying on hooks in this context is a mental mapping every developer in the team has to be aware of.
  2. Quitting the program "normally" provides the same exit code to the operating system as System.exit(0) so it is redundant.

    If your program cannot quit "normally" you have lost control of your development [design]. You should have always full control of the system state.

  3. Programming problems such as running threads that are not stopped normally become hidden.
  4. You may encounter an inconsistent application state interrupting threads abnormally. (Refer to #3)

By the way: Returning other return codes than 0 does make sense if you want to indicate abnormal program termination.

TT--
  • 2,956
  • 1
  • 27
  • 46
oopexpert
  • 767
  • 7
  • 12
  • 2
    "You should have always full control of the system state." That is simply not possible in Java. IoC frameworks and application servers are only 2 very popular and widely used ways you give up your control of the system state. And that's totally fine. – mhlz Sep 29 '15 at 12:50
  • Please execute System.exit(0) in your application server and tell me about the reactions of your server admin... You missed the subject of this question and my answer. – oopexpert Sep 30 '15 at 19:27
  • Maybe I was not clear enough. You should have always have full control of the system state you are responsible for. Yes, some responsibilities were shifted into application servers and IoC. But I wasn't talking about that. – oopexpert Sep 30 '15 at 19:40
7

Though answer was really helpful but some how it missed some more extra detail. I hope below will help understand the shutdown process in java, in addition to the answer above:

  1. In an orderly* shutdown, the JVM first starts all registered shutdown hooks. Shutdown hooks are unstarted threads that are registered with Runtime.addShutdownHook.
  2. JVM makes no guarantees on the order in which shutdown hooks are started. If any application threads (daemon or nondaemon) are still running at shutdown time, they continue to run concurrently with the shutdown process.
  3. When all shutdown hooks have completed, the JVM may choose to run finalizers if runFinalizersOnExit is true, and then halts.
  4. JVM makes no attempt to stop or interrupt any application threads that are still running at shutdown time; they are abruptly terminated when the JVM eventually halts.
  5. If the shutdown hooks or finalizers don’t complete, then the orderly shutdown process “hangs” and the JVM must be shut down abruptly.
  6. In an abrupt shutdown, the JVM is not required to do anything other than halt the JVM; shutdown hooks will not run.

PS: The JVM can shut down in either an orderly or abrupt manner.

  1. An orderly shutdown is initiated when the last “normal” (nondaemon) thread terminates, someone calls System.exit, or by other platform-specific means (such as sending a SIGINT or hitting Ctrl-C).
  2. While above is the standard and preferred way for the JVM to shut down, it can also be shut down abruptly by calling Runtime.halt or by killing the JVM process through the operating system (such as sending a SIGKILL).
John
  • 371
  • 3
  • 11
5

System.exit is needed

  • when you want to return a non-0 error code
  • when you want to exit your program from somewhere that isn't main()

In your case, it does the exact same thing as the simple return-from-main.

mfx
  • 7,168
  • 26
  • 29
  • What do you mean with the latter? The proper way to shut down the program is stopping all threads (nicely), a move which does not have to be initiated from the main thread, so it's not like `exit` is your only option there. – Bart van Heukelom Sep 15 '10 at 08:49
  • @Bart: what you describe is *one of the possible ways* to shut down a program, not *the proper way*. There's nothing wrong in using shutdown hooks to stop all threads nicely. And shutdown hooks are launched with `exit`. Not the only option, but definitely an option worth considering. – Joonas Pulakka Sep 15 '10 at 08:53
  • But what I gather from the docs, shutdown hooks are very delicate and may not have a lot of time to do what you want them to do. By all means, use them to quit nicely in case of an OS shutdown or something, but if you're going to call System.exit() yourself I think it's better to do the shutdown code before it (after which you will probably not need System.exit() any more) – Bart van Heukelom Sep 15 '10 at 08:59
  • 1
    Shutdown hooks do have all the time they take to finish. The VM is not halted before all the hooks have returned. It's indeed possible to prevent the VM from quitting by registering a shutdown hook that takes very long time to execute. But of course it's possible to do the shutdown sequence in various, alternative ways. – Joonas Pulakka Sep 15 '10 at 09:36
  • Returning from main will not shut down if there are other non-daemon threads. – djechlin Nov 06 '13 at 21:33
4

Java Language Specification says that

Program Exit

A program terminates all its activity and exits when one of two things happens:

All the threads that are not daemon threads terminate.

Some thread invokes the exit method of class Runtime or class System, and the exit operation is not forbidden by the security manager.

It means that You should use it when You have big program (well, at lest bigger than this one) and want to finish its execution.

Community
  • 1
  • 1
Marcin Szymczak
  • 11,199
  • 5
  • 55
  • 63
3

If you have another program running in the JVM and you use System.exit, that second program will be closed, too. Imagine for example that you run a java job on a cluster node and that the java program that manages the cluster node runs in the same JVM. If the job would use System.exit it would not only quit the job but also "shut down the complete node". You would not be able to send another job to that cluster node since the management program has been closed accidentally.

Therefore, do not use System.exit if you want to be able to control your program from another java program within the same JVM.

Use System.exit if you want to close the complete JVM on purpose and if you want to take advantage of the possibilities that have been described in the other answers (e.g. shut down hooks: Java shutdown hook, non-zero return value for command line calls: How to get the exit status of a Java program in Windows batch file).

Also have a look at Runtime Exceptions: System.exit(num) or throw a RuntimeException from main?

Community
  • 1
  • 1
Stefan
  • 10,010
  • 7
  • 61
  • 117