Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run code after a call to Sytem.exit(0) in a finally block

Tags:

java

I have three classes say alpha, beta, gamma and each of the three classes has a main method.

Both alpha and beta classes have, inside their main method, a try...catch...finally block like:

public class alpha{

    public static void main(String[] args){
        try{
            Do something;
        }catch(Exception ex){
            ex.printStackTrace();
        }
        finally{
            System.exit(0);
        }
    }
}


public class beta{

    public static void main(String[] args){
        try{
            Do something;
         }catch(Exception ex){
            ex.printStackTrace();
        }
        finally{
            System.exit(0);
        }
    }
}

Now in gamma class i call main methods of alpha and beta classes to run continuously like below

public gamma{

    public static void main(String[] args) {
        try {
            alpha.main(arg);
            beta.main(arg1);
        } catch (Exception e) {
            e.printStackTrace();
        }
}

The problem is that the code beta.main(arg1) is never reached due to the System.exit(0) inside the alpha class's finally block. Since alpha and beta are standalone applications when they executed separately they should terminate the service at the end of program. So now this there any way to reach the beta.main(arg1) line without much changing the actual functionality of alpha and beta classes.

Kindly let me know if you need further details. Thanks in advance...

like image 743
coolgokul Avatar asked Jan 04 '12 16:01

coolgokul


3 Answers

In such case, shutdown hook can be used:

public class Gamma{

    public static void main(String[] args) {
        try {
        Thread hook = new Thread() { public void run() { Beta.main(args); } };
            hook.setDaemon(true);
            Runtime.getRuntime().addShutdownHook(hook);
            Alpha.main(args);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
like image 125
Vlad Avatar answered Oct 21 '22 03:10

Vlad


(Ideally, nothing that is part of a module's public API should ever do anything that calls exit, and the main method of a class should just be a small shim that invokes something else that does the real work before producing the proper exit code.)

That said, if you want to prevent System.exit, you can register a SecurityManager that converts calls to System.exit into SecurityExceptions or Errors.

System.exit:

throws

SecurityException - if a security manager exists and its checkExit method doesn't allow exit with the specified status.

Something like

System.setSecurityManager(new SecurityManager() {
  @Override
  public void checkExit(int exitCode) throws SecurityException {
    throw new SecurityException("stop that");
  }
});

Then the method which is calling main methods can just catch and suppress that SecurityException. You could make it more robust by creating your own ExitCalledError and throwing that instead and only suppressing that.

I find this very useful for preventing unit-test runners from spuriously reporting success when the test runner is exited by code under test with a zero exit code.

like image 32
Mike Samuel Avatar answered Oct 21 '22 03:10

Mike Samuel


Really, the only solution is to get rid of the System.exit() call. This is why System.exit() is evil. A good way to replace them is by throwing an exception -- you can add an exception handler to the system (look into adding them to ThreadGroups to add one for every exception path) and then decide what you want to do.

like image 1
Charlie Martin Avatar answered Oct 21 '22 03:10

Charlie Martin