如何从不同的线程“捕获”System.exit(-1)?

时间:2012-04-14 12:55:21

标签: java multithreading jvm securitymanager system.exit

我有以下

System.setSecurityManager(new SecurityManager() {
    @Override
    public void checkExit(int status) {
        super.checkExit(status);

        //custom exception extends SecurityException
        throw new SystemExitCalledException();
    }
});

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        //never reaches here somehow... 
        //maybe some3rdPartyStaticMethod sets this, too?
    }

});


try {
    //this method spawns threads and some call System.exit().
    some3rdPartyStaticMethod.invoke(null, new Object[]{args});
} catch (SystemExitCalledException e) {
    //it never reaches here because 
    //SystemExitCalledException is thrown on different thread?? 
    //
}

有没有办法阻止some3rdPartyStaticMethod的生成线程的System.exit()调用停止jvm?

2 个答案:

答案 0 :(得分:2)

您可以在单独的进程中启动代码,并使用RMI与其进行通信。如果第三方代码调用System.exit并终止其进程,则您的进程可以继续运行并在必要时重新创建子进程。

请注意,这种方法有一些注意事项:

  • 这两个进程不共享相同的堆空间。
  • 您需要封送在两个进程之间传递的所有数据。这意味着数据必须是可序列化的。
  • 每次方法调用都会有相当大的开销。如果您需要每秒进行多次调用,这可能会导致性能问题。

答案 1 :(得分:1)

编写自定义SecurityManager策略应该有所帮助 - 我自己从未这样做过:)

根据this post(向下滚动到底部):

  

但是,当VM中的任何内容尝试调用System.exit()时,VM将退出。由于这包括mvn的残酷击落,正常的mvn进程被中断。 SecurityManager可用于防止代码调用System.exit(),但没有人提到副作用。

     

我的一位同事提到,您可以在启动VM时在系统范围内,按用户和系统属性设置策略,经过快速测试后,这已经证明可以解决我的问题。我已经设法从我的代码中设置自己的策略(在设置SecurityManager之前),这解决了我的问题。

     

我使用了以下代码:

//Setup security to prevent System.exit()
SecurityManager sm = System.getSecurityManager();
URL policy = getClass().getClassLoader().getResource("jsdoc.policy");
System.setProperty("java.security.policy", policy.toString());
System.setSecurityManager(new JSDocSecurityManager(getLog()));
  

使用简单,开放的政策文件阅读:

grant {
  permission java.security.AllPermission;
};

如果有效,它应该捕获System.exit()请求并抛出SecurityException而不是