ѕтƒ
ѕтƒ

Reputation: 3647

Alternates for System.exit that could send error codes to batch or shell

I have a set of error codes in my java application. Currently I'm using System.exit(code); to return error codes from the application to external applications. Is there any alternatives of System.exit as using this is bad practice because it may shutdown the entire JVM.

Upvotes: 0

Views: 1888

Answers (3)

robert
robert

Reputation: 4867

I have shared your experience in the past, and tried to engineer out System.exit(). One possibility is to leave a RuntimeException uncaught and you will return 1 to the shell, but ultimately if you want any more versatility than that (and don't want an ugly stack-trace polluting your output), you must have at least "one" call to System.exit().

public class Splat {

    public static void main(String[] args) {

        if (args.length > 0 && "splat".equals(args[0]))
            throw new RuntimeException("splat");
    }
}

Output:

 $ java Splat
 $ echo $?
 > 0
 $ java Splat splat
 > Exception in thread "main" java.lang.RuntimeException: splat
 >         at Splat.main(Splat.java:9)
 $ echo $?
 > 1

My reason for doing this was our organisation started using static analysis results from sonar as a KPI and it was my job to get the numbers down. It's a terrible reason for doing anything, but an interesting engineering challenge nonetheless ....

An approach I tried was throwing a specific class of RuntimeException, with an exit-code instance variable, and catching it at the outer scope. That way you can be sure that when you do murder the VM you're at the tail of the stack anyway ...

public class Splat {

    public static final class Exit extends RuntimeException {

        private int exitCode;

        public Exit(int exitCode) {
            this.exitCode = exitCode;
        }
    }

    public static void main(String[] args) {

        try {

            wrappedMain(args);

        } catch (Exit e) {

            System.exit(e.exitCode);
        }
    }

    public static void wrappedMain(String[] args) {

        if (args.length > 0 && "splat".equals(args[0])) {

            int code = (args.length > 1) ? Integer.parseInt(args[1]) : 0;

            throw new Exit(code);
        }
    }
}

Output:

 $ java Splat
 $ java Splat splat
 $ echo $?
 > 0
 $ java Splat splat 1
 $ echo $?
 > 1
 > $ java Splat splat 2
 $ echo $?
 > 2
 $ java Splat splat -1
 $ echo $?
 > 127

There are caveats to this approach of course! It is a bit of an odd way to exit and anybody unfamiliar with your constraints will scratch their head. Also, if somebody does catch (Throwable t) later on, then you wont be able to exit!!! If you are working in a static analysis CI environment then that should be quickly highlighted as a more grievous violation!

Upvotes: 2

Codebender
Codebender

Reputation: 14471

If you are talking about the exit code of a process then System.exit(int) is the way to go since you want the whole process to exit and so the JVM should shutdown as well.
But if you want to send out some error messages to the batch or shell (without exiting the process) then you will have to use System.err.println(). This will write to the error stream instead of the output stream.

Upvotes: 0

Abacus
Abacus

Reputation: 19421

As already commented: When you wait for some code in a batch or shell you are actually waiting for the program to finish and that means your java program exits and so does the JVM. And the one and only way is then to use System.exit(code) as you are already doing.

Upvotes: 0

Related Questions