System.exit(num) or throw a RuntimeException from main?
Asked Answered
T

7

25

I've got a single threaded app that should set the DOS errorlevel to something non-zero if there is a problem. Is it better to throw a RuntimeException, or to use System.exit(nonzero)? I don't need the stack trace, and I don't expect this app to be extended/reused. What are the differences between these two options?

Tingly answered 18/8, 2010 at 23:50 Comment(2)
You seem to have answered your own question. If you have to set a DOS error code you have to use System.exit(code). You can't do that with an exception.Isopropyl
Thowing a RuntimeException from main sets errorlevel to 3, though I'm not sure why or if it's under all circumstances.Tingly
D
12

Don't throw an exception unless you really have an exceptional condition. System.exit(int) is there for precisely this reason. Use it.

EDIT: I think I may have misread your question. I thought you were asking, when you want to exit the JVM normally but signal that something did not quite go right, whether it is better to throw an exception or to use System.exit.

However, if the problem that occurs is something which is already indicated by a Java exception, it's fine to just let that exception go unhandled. You don't have to catch the exception and call System.exit.

If you have a choice of whether to throw an exception of your own or call System.exit, think about whether the error condition is something that might conceivably be handled by some Java code that calls your method. If the error occurs directly in the main method, then there will probably never be a caller to handle the exception so you should probably call System.exit. Otherwise, it's generally best to throw an exception - but not RuntimeException, you should probably use an exception type that appropriately represents the error you encountered. Write your own subclass of RuntimeException if necessary.

Dansby answered 18/8, 2010 at 23:53 Comment(2)
Then why do exceptions thrown from main set the errorlevel? It seems they are there for some reason.Tingly
When an application does not finish successfully, its return code should be something other than 0. So the JVM will automatically set the return code to 1 if there is an unhandled exception, so that the parent process knows that your program terminated because of an error (and not just because it finished working).Dansby
P
7

Generally in this situation I would handle all exceptions in my main method, possibly by calling System.exit. This gives you flexibility about where/whether/how to handle exceptional conditions, while still meeting your need to terminate with an error code. In particular, it gives you control over the return code and any other output you might generate for the user (error message, stack trace, etc). If you throw an exception in main (or let an exception escape), you lose that control.

To summarize, call System.exit only in your top-level exception handler:

static public void main() {
   try {
      runMyApp();
   } catch (Exception e) {
      System.exit(1);
   }
}
Perren answered 19/8, 2010 at 0:50 Comment(1)
I'll probably go with this solution, but I was fishing for the reasons why System.exit is preferred over throwing an exception from main.Tingly
F
4

An exception thrown will print out the stack trace, and if you don't need that, you shoul use System.exit.

Upon exit you can inform the user with a Sytem.out (I assume the app is running in a commanline environment only).

You should consider just catching all errors an logging the errors in a seperate log, this ensures the stacktrace is not lost forever when you close the terminal. Take a look at log4j for this purpose, it's really easy to use.

Foldaway answered 19/8, 2010 at 2:44 Comment(2)
Yes, it's in a commandline environment only. I don't need the stack trace because it's an automated step in our build process that either passes or fails, so even log4j is overkill.Tingly
Then go for the system.exit solution. It's a good solution especially if you check the return code afterwards. That way you can signal what went wrong using different codes, or just go for System.exit(-1)Foldaway
G
2

The APP itself should use System.exit. It's its interface with the calling environment (script). Any internal component of course should use Exception. When you put it together it can be the both of'em:

Application.main(...) {
  parse(args);
  check(...);
  try {
    MyObject o = ...;
    o.doMyStuff();
  } catch (Exception e) {
    System.err.println("Oops, something went wrong!"); // by example, or use a logging framework! // anyway in a shell app System.in/out/err IS my interface with the outworld
    System.exit(ERROR_CODE);
  }
  System.out.println("Worked!");
}
Gastrin answered 19/8, 2010 at 8:12 Comment(0)
H
0

It depends how much information you want to report back to the script that starts your program. This can be very important if the script is designed to execute a chain of actions. https://shapeshed.com/unix-exit-codes/

Example: I developed a Java program that calls an external API, downloads the response and saves it to a file. Possible outcomes:

  • 0 = OK
  • 5 = HTTP Temporarily unavailable
  • 6 = Unable to write file to disk

Now my script knows what went wrong, and it could take different actions based on the outcome.

  • If response = 0, continue next step in the script
  • If response = 5, retry (with a delay)
  • If response = 6, stop the script

Bottom line: like any good api, clearly define your input and output parameters and use System.exit.

Hormonal answered 12/2, 2020 at 9:4 Comment(0)
J
-2

System.exit(num) is not a good option, as its shutdown JVM, plus even it didnt run the finally block if you have after catch block.

Throwing RuntimeException also might not be the best of the option, can subclass as mentioned earlier which is app specific exception could be a better option in my opinion. -Manish

Joust answered 28/10, 2011 at 20:20 Comment(0)
P
-5

System.exit() not recommended. It shutdowns JVM.

Pacifa answered 18/8, 2010 at 23:54 Comment(6)
Shutting down the JVM is OK in this case, the application is done if there is an error.Tingly
neither generic RuntimeException is advised in my opinionPacifa
either system.exit(int) or throw new RuntimeException, isn't the latter considered a generic RuntimeException?Tingly
yes. Throwing RuntimeException is better compared to calling System.exit(int)Pacifa
I generally agree with you. I was looking more for the "why" part, but there may not be advantages to either method in this case. I'm mostly worried that the errorlevel set from throwing an exception isn't consistent, but neither is the errorlevel set from System.Exit(num) because it can throw an exception itself.Tingly
I appreciate counter opinions, but please explain them.Voter

© 2022 - 2024 — McMap. All rights reserved.