捕获库的退出指令

发布于 2024-10-15 02:08:14 字数 223 浏览 4 评论 0原文

令我惊讶和恐惧的是,我刚刚在我使用的库中遇到了 System.exit(1); 行。我计划联系该库的作者并询问提供了什么,但同时有什么方法可以防止该库杀死我的代码(更糟糕的是,使用我的代码杀死应用程序)?

也许以某种方式强制库抛出一个 SecurityException,我看到 exit(int) 可能会抛出这个异常?

To my astonishment and horror, I've just encountered the line System.exit(1); in a library I use. I'm planning on contacting the library's authors and asking what gives, but meanwhile is there any way to prevent the library from killing my code (and worse, killing the application using my code)?

Perhaps somehow force the library to throw a SecurityException, which I see that exit(int) may throw?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

风向决定发型 2024-10-22 02:08:14

我只知道一种方法,那就是编写一个 SecurityManager 来禁止使用 System.exit。

public class MySecurityMgr extends SecurityManager {
   ... 

   @Override
    public void checkExit(int status) {
            throw new RuntimeException(Integer.toString(status));
    }
}

There is only one way I know of, and that is to code a SecurityManager which disallows the use of System.exit.

public class MySecurityMgr extends SecurityManager {
   ... 

   @Override
    public void checkExit(int status) {
            throw new RuntimeException(Integer.toString(status));
    }
}
烟沫凡尘 2024-10-22 02:08:14

我认为你唯一的选择(除了用湿毛巾殴打作者直到他重写该死的东西)是更改库的字节代码。

漂亮的方法是在加载库时使用 AspectJ 和加载时编织,丑陋的选择是使用像 asm 这样的工具来删除或更改方法调用。

这是一个 AspectJ 方面,它会偏转对 System.exit() 的调用:

public aspect SystemExitEvader{

    pointcut systemExitCall() : call(* java.lang.System.exit(*));

    void around() : systemExitCall(){
        System.out.println("Call to System.exit() attempted");
        // note: there is no call to proceed()
    }

}

好的,我已经看到了有关 SecurityManagers 的其他答案,我同意这可能是要走的路,但我将在这里留下我的答案作为替代方案。

I think your only choice (short of whacking the author with wet towels until he rewrites the damn thing) would be to change the library's byte code.

The pretty approach is to use AspectJ with load time weaving when you load the library, the ugly option is to use a tool like asm to either delete or change the method call.

Here's an AspectJ aspect that deflects calls to System.exit():

public aspect SystemExitEvader{

    pointcut systemExitCall() : call(* java.lang.System.exit(*));

    void around() : systemExitCall(){
        System.out.println("Call to System.exit() attempted");
        // note: there is no call to proceed()
    }

}

OK, I've seen the other answers about SecurityManagers and I agree that's probably the way to go, but I'll leave my answer here as an alternative.

因为看清所以看轻 2024-10-22 02:08:14

是的,您可以安装覆盖 checkExit

我发现这对于单元测试代码特别有用,可以确保测试的代码不会以 0 退出,这表明在测试有机会运行完成之前出现了虚假的成功。

如果 SecurityException 最终杀死了一些通常寿命较长的基本线程,这将无济于事。

Yes, you can install a SecurityManager that overrides checkExit.

I've found this particularly useful for unittesting code to make sure that tested code doesn't exit with 0, indicating spurious success before the tests have a chance to run to completion.

This won't help though if the SecurityException ends up killing some normally long-lived essential thread.

梨涡少年 2024-10-22 02:08:14

是的,安全经理可以解决这个问题

// install security manager to avoid System.exit() call from lib
SecurityManager       previousSecurityManager = System.getSecurityManager();
final SecurityManager securityManager         = new SecurityManager() {
    @Override public void checkPermission(final Permission permission) {
      if (permission.getName() != null && permission.getName().startsWith("exitVM")) {
        throw new SecurityException();
      }
    }
  };
System.setSecurityManager(securityManager);

try {
   // Call here your lib code
} catch (SecurityException e) {
  // Say hi to your favorite creator of closed source software that includes System.exit() in his code.
} finally {
  System.setSecurityManager(previousSecurityManager);
}

yes security manager can do the trick

// install security manager to avoid System.exit() call from lib
SecurityManager       previousSecurityManager = System.getSecurityManager();
final SecurityManager securityManager         = new SecurityManager() {
    @Override public void checkPermission(final Permission permission) {
      if (permission.getName() != null && permission.getName().startsWith("exitVM")) {
        throw new SecurityException();
      }
    }
  };
System.setSecurityManager(securityManager);

try {
   // Call here your lib code
} catch (SecurityException e) {
  // Say hi to your favorite creator of closed source software that includes System.exit() in his code.
} finally {
  System.setSecurityManager(previousSecurityManager);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文