1

我有以下

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?

4

2 回答 2

2

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

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

  • 这两个进程不共享相同的堆空间。
  • 您将需要编组在两个进程之间传递的所有数据。这意味着数据必须是可序列化的。
  • 每个方法调用都会有相当大的开销。如果您需要每秒进行多次调用,这可能会导致性能问题。
于 2012-04-14T13:01:28.053 回答
1

编写自定义 SecurityManager 策略应该会有所帮助——我自己从来没有这样做过 :)

根据这篇文章(向下滚动到底部):

但是,当 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改为抛出

于 2012-04-14T13:09:06.420 回答