【问题标题】:How can I "capture" System.exit(-1) from different thread?如何从不同的线程“捕获” System.exit(-1)?
【发布时间】:2012-04-14 12:55:21
【问题描述】:

我有以下

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?

【问题讨论】:

  • 也许您可以使用 'SecurityManager' 将调用 'Shutdown.exit' 替换为 'SecurityException'。

标签: java multithreading jvm securitymanager system.exit


【解决方案1】:

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

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

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

【讨论】:

  • +1 限制与您不信任的代码的交互是一件好事。这样它就有自己的堆限制。等
  • 当然,但是 Java 确实有针对这些东西的 SecurityManager,它避免了整个 IPC 的东西。不知道为什么这对他不起作用 - 可能是政策文件的位置错误?
【解决方案2】:

编写自定义 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

【讨论】:

    猜你喜欢
    • 2010-10-29
    • 2011-09-26
    • 2010-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多