【问题标题】:Determine exit status within the java shutdown hook thread在 java 关闭钩子线程中确定退出状态
【发布时间】:2009-09-28 11:58:04
【问题描述】:

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

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

(例如:如果零不做任何其他非零发送警报电子邮件)

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

【问题讨论】:

    标签: java shutdown application-shutdown


    【解决方案1】:

    我试图覆盖 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);
            }
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      这里是一些示例代码,其中使用专用类通过调用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 ...
            }
          }
        }
      }
      

      【讨论】:

      • 是的,包装退出方法并在应用程序代码中使用它是一种选择,但不是最好的!我期待一个由 java sdk 提供的 exitStatus 属性,尽管它似乎不可用。
      【解决方案3】:

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

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

      Shutdownhooks 应该只运行很短的时间,发送电子邮件可能会消耗相当长的时间。

      【讨论】:

      • 我同意。这种情况应该不在应用程序代码库中,并且外部的东西可以处理电子邮件警报。该应用程序使用 tanuki wrapper 社区版作为服务在 NT 机器上运行。包装器提供电子邮件通知,但仅在其付费版本中。您是否知道可以管理电子邮件通知的免费/开源配置?
      【解决方案4】:

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

      【讨论】:

      • 为什么要在 main 中专门设置一个公共静态变量?在调用 System.exit 之前,退出状态不能传递给充当关闭挂钩的对象吗?
      • 全局变量只是最简单的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多