确定java shutdown hook线程中的退出状态

我想确定关闭钩子运行时期间进程的退出状态。

我想要一个基于状态代码(0或非零)的逻辑

(例如:如果零则不执行其他非零发送警报电子邮件)

你知道我怎么能得到这些信息吗?

我试图覆盖SecurityManager checkExit(int status)方法 – 如果在任何地方显式调用System.exit(status) ,这是有效的 – 但是,当应用程序退出“正常”(没有活动线程)时,它不会设置状态,或者错误会杀死VM。

 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.security.Permission; public class ExitChecker { public ExitChecker() { System.setSecurityManager(new ExitMonitorSecurityManager()); Runtime.getRuntime().addShutdownHook(new Thread(new MyShutdownHook())); BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); String line = ""; while (!line.equalsIgnoreCase("Q")) { try { System.out.println("Press a number to exit with that status."); System.out.println("Press 'R' to generate a RuntimeException."); System.out.println("Press 'O' to generate an OutOfMemoryError."); System.out.println("Press 'Q' to exit normally."); line = input.readLine().trim(); processInput(line); } catch (IOException e) { e.printStackTrace(); System.exit(-1); } } } private void processInput(String line) { if (line.equalsIgnoreCase("Q")) { // continue, will exit loop and exit normally } else if (line.equalsIgnoreCase("R")) { throwRuntimeException(); } else if (line.equals("O")) { throwError(); } else { // try to parse to number try { int status = Integer.parseInt(line); callExit(status); } catch(NumberFormatException x) { // not a number.. repeat question... System.out.println("\nUnrecognized input...\n\n"); } } } public void callExit(int status) { System.exit(status); } public void throwError() { throw new OutOfMemoryError("OutOfMemoryError"); } public void throwRuntimeException() { throw new RuntimeException("Runtime Exception"); } public static void main(String[] args) { new ExitChecker(); } private static class ExitMonitorSecurityManager extends SecurityManager { @Override public void checkPermission(Permission perm) { //System.out.println(perm.getName()); //System.out.println(perm.getActions()); } @Override public void checkPermission(Permission perm, Object context) { //System.out.println(perm.getName()); //System.out.println(perm.getActions()); } @Override public void checkExit(int status) { System.out.println("Setting exit value via security manager..."); MyShutdownHook.EXIT_STATUS = status; } } private static class MyShutdownHook implements Runnable { public static Integer EXIT_STATUS; public void run() { System.out.println("In MyShutdownHook - exit status is " + EXIT_STATUS); } } } 

下面是一些示例代码,通过调用doExit(int) ,使用专用类来启动System.exit调用。 该类还存储退出状态,随后充当关闭挂钩。

 public class ShutDownHook implements Runnable { private volatile Integer exitStatus; // Centralise all System.exit code under control of this class. public void doExit(int exitStatus) { this.exitStatus = exitStatus; System.exit(exitStatus); // Will invoke run. } public void run() { // Verify that an exit status has been supplied. // (Application could have called System.exit(int) directly.) if (this.exitStatus != null) { switch(exitStatus) { case 0: // Process based on exit status. // Yada yada ... } } } } 

为什么在应用程序中这样做呢? 如果你的应用程序没有发送电子邮件作为正常操作的一部分,那么结合这种function并不是一个好主意,恕我直言。

我只相信从JVM进程设置一个适当的返回值,并让shell脚本或其他任何负责条件创建电子邮件。

Shutdownhooks应该只运行一小段时间,发送电子邮件可能会耗费相当长的时间。

您必须将main的退出状态保存到全局( public static )变量中。