3

If I have a program that invokes a method which must terminate if a particular exception is thrown, should I design it such that the exception is passed up back to main so it can safely return, or should I handle the exception in the function and invoke System.exit(-1)?

Here is an example of what I mean by handling it in the function:

public class MyClass{
     public static void main (String[] args){
        myFunction(args);
     }
     public static void myFunction(String[] args){
          try{
              if(args.length == 0) 
                   throw Exception("Invalid Input");
          }catch(Exception e){
              System.out.println(e);
              System.exit(-1);
          }
     }
 }

Here is an example of what I mean by passing it up:

public class MyClass{
     public static void main (String[] args){
        try{
             myFunction(args);
        }catch(Exception e){ 
             System.out.println(e);
        }
     }
     public static void myFunction(String[] args) throws Exception{
         if(args.length == 0)
              throw Exception("Invalid Input");
     }
 }

Which way should be used in this situation?

0xCursor
  • 2,242
  • 4
  • 15
  • 33
user1939991
  • 187
  • 4
  • 14
  • 2
    The program will terminate if you just let the exception to be thrown uncaught from `main()`. Why do you want to _catch_ the exception if it's fatal? Also, `catch(Exception e){ System.exit(-1); }` is usually never a good idea. – Mick Mnemonic Aug 01 '18 at 00:05
  • It is an exception that is thrown due to invalid input, which isn't fatal to the program but requires that I exit the program. – user1939991 Aug 01 '18 at 00:08
  • Okay, then it would be better if you'd actually share some relevant code. – Mick Mnemonic Aug 01 '18 at 00:10
  • @MickMnemonic The actual code is long, so I modified the example so that it represents my situation. The reason why I exit is because the program cannot continue if the input is not supplied correctly in the example. – user1939991 Aug 01 '18 at 00:18
  • 1
    I gotta say.. This is one of the most intelligent/thought-provoking question I've seen in a while. – Taslim Oseni Aug 01 '18 at 00:38
  • Please read [Why is asking a question on “best practice” a bad thing?](https://meta.stackexchange.com/questions/142353/why-is-asking-a-question-on-best-practice-a-bad-thing/243450) before attempting to ask more questions that are opinion based that invite argumentative discussion because they do not have a single agreed upon answer. –  Aug 01 '18 at 04:57
  • **Primarily Opinion Based** - *Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise.* Please read [What types of questions should I avoid asking?](http://stackoverflow.com/help/dont-ask) before attempting to ask more questions. –  Aug 01 '18 at 04:57
  • As my answer indicates, this question is at heart not primarily opinion based, and has an answer justified on technical grounds. – Raedwald Aug 01 '18 at 07:55

4 Answers4

1

This is a pretty hard question to me, I just share some ideas in my mind now.

There are two major factors you need to care for:

  1. Is it fatal? can you prevent it from destroying/shutting down the program?
  2. Can you do something to the exception? Record some useful information? Restore it by some methods?

No.1

If it's fatal then you'd better try to make sure the program exit gracefully by catching it in proper layer perhaps right there where the exception throws or higher (which depends more on the No.2);

No.2

If you want to track some useful information for debug or even for restoration if it's possible.

Then whether you catch it and handle it where depends on your project/system.

Take a normal case as an example:

If you need to track the information in calling layer, you should catch the exception in lower layer and throw the exception to let the calling/higher layer to have it:

  1. either log some useful info for debug
  2. or restore it by other methods (like you have strategy patten introduced, perhaps then you should try other strategy to replace the current one to process the same job);

Another word

Please do NOT try to introduce exception to your project/system logic, exception should be treated as exceptions handling unexpected issues.

Sorry to add this, hope it might be helpful.

Hearen
  • 7,420
  • 4
  • 53
  • 63
0

From this post:

You should catch the exception when you are in the method that knows what to do.

If the method the exception is thrown in knows how to handle the error, then it should handle it. Otherwise, if the method doesn't know what to do with the exception, it should throw it.

In your problem, as you want to exit the program when the exception occurs, it would probably make sense to throw the exception back to the main method.

This post also has some good information.

0xCursor
  • 2,242
  • 4
  • 15
  • 33
0

There’s very little reason to call System.exit. Maybe if there was some disastrous condition where you wanted to stop the JVM immediately, it’s hard to imagine what it would be. So I would say, never call System.exit without some very specific requirement.

Set up a try-catch block in the main method, catch Throwable, and log it. That minimizes the exception-handling elsewhere in the program and encourages a fail-fast way of programming so that exceptions don’t get eaten and lost.

Alternatively, maybe you have a small Java program run from a shell script. You could let the main method throw Exception and let the shell script caller redirect stderr to a file. But using a real logger gives more control over rolling and purging, etc.

If you’re worried some error could be thrown that can’t be logged (maybe we’re out of memory and can’t log without causing another out of memory error), add the logging to the caller in addition to having the Java program do its own logging, as a precaution.

0xCursor
  • 2,242
  • 4
  • 15
  • 33
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • So since I need to exit here, you would recommend passing it back up to main to log the error and return safely? – user1939991 Aug 01 '18 at 00:23
  • @user1939991: in general yes. What you want to avoid is catching some exception too close to the source where where now the program is in a bad state and proceeding from there will only cause more errors. You use the exception to move control to a safe place. – Nathan Hughes Aug 01 '18 at 00:26
0

This question can be answered in a manner that indicates, at heart, it is not a primarily opinion based question.

First, consider the related question "when should you throw an exception"? The correct answer to this is "If, and only if, the alternative would be to fail to establish a post condition or maintain an invariant". That reminds us to think in terms of method post conditions. You provide an example of a method for parsing the command line arguments. That should have a post condition of "the command line arguments are valid". So in the event of the command line arguments being invalid, that rule tells us that the method should throw an exception, and need not terminate.

Second, consider why have exceptions at all. There are programming languages without them (in particular, C). The alternative is to uses status codes. One of the advantages of exceptions is that they separate detection of problems (where you throw an exception) from deciding what to do in the event of a problem (where you catch exceptions). They provide a means for "pushing policy upwards", to the higher level calling methods. So, in the event of a problem (such as invalid command line arguments, in your example), should the program terminate? That is a question of policy, and so belongs in a higher level method, not in a low level method. And the same argument applies throughout all the levels of the program: no method can ever be justified as terminating the program, implementing the most drastic policy possible, because it can instead push the policy upwards by throwing an exception. The only method that can't push policy upwards is the main method, because it has no caller to push upwards to. That suggests only the main method should ever cause the program to terminate. Note that the JVM operates in this manner: even virtual machine errors that can not be handled at all, and should result in program termination, result in a VirtualMachineError being thrown, rather than direct program termination.

Raedwald
  • 46,613
  • 43
  • 151
  • 237