阻止 API 中的 System.exit()
我正在使用一个第三方库,如果遇到异常,它会执行 System.exit()
。我正在使用 jar 中的 API。无论如何,我是否可以阻止 System.exit()
调用,因为它会导致我的应用程序关闭?由于许多其他许可问题,在删除 System.exit() 后我无法反编译和重新编译 jar。我曾经在 stackoverflow 中[对其他一些我不记得的问题]找到了一个答案,我们可以在 Java 中使用 SecurityManager
来做这样的事情。
I am using a third party library that does a System.exit()
if it encounters exceptions. I am using the APIs from a jar. Is there anyway that I can prevent the System.exit()
call because it causes my application to shutdown? I cannot decompile and recompile the jar after removing the System.exit()
because of a lot of other licensing issues. I once came across an answer [to some other question that I do not remember] in stackoverflow that we can use the SecurityManager
in Java to do something like this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以安装禁用
System.exit()
的安全管理器:编辑: Max 在下面的评论中指出
但是,权限
exitVM.*
指的是所有退出状态,并且exitVM
被保留作为exitVM.*
的简写,所以上面的代码仍然有效(请参阅 RuntimePermission< 的文档/代码>)。You can install a security manager which disables
System.exit()
:Edit: Max points out in comments below that
However, the permission
exitVM.*
refers to all exit statuses, andexitVM
is retained as a shorthand forexitVM.*
, so the above code still works (see the documentation forRuntimePermission
).请参阅我对 如何避免 JFrame EXIT_ON_CLOSE 操作退出整个应用程序?。
编辑1:链接的来源。演示如何使用
SecurityManager
来阻止System.exit(n)
。See my reply to How to avoid JFrame EXIT_ON_CLOSE operation to exit the entire application?.
Edit 1: The source that was linked. Demonstrates how to use a
SecurityManager
to preventSystem.exit(n)
.前面的代码示例部分正确,但我发现它最终阻止了我的代码对文件的访问。为了解决这个问题,我编写的 SecurityManager 有点不同:
在我的例子中,我需要防止第三方库终止虚拟机。但也有一些 grails 测试调用 System.exit。因此,我编写了代码,以便它仅在调用第 3 方库之前立即激活自定义安全管理器(不是常见事件),然后立即恢复原始安全管理器(如果有)。
这一切都有点丑陋。理想情况下,我更愿意简单地删除 System.exit 代码,但我无权访问第 3 方库的源代码。
The previous code sample is partially correct, but I found that it ended up blocking my code's access to files. To get around that problem, I wrote my SecurityManager a little differently:
In my case, I needed to prevent a 3rd party library from terminating the VM. But there were also some grails tests that were calling System.exit. So, I wrote my code so that it only activated the custom security manager immediately before the call to the 3rd party library (not a common event) and then immediately restored the original security manager, if any, afterwards.
It's all a little ugly. Ideally, I would have preferred to simply remove the System.exit code, but I do not have access to the 3rd party library's source code.
使用 SecurityManager 禁止 System.exit() 调用并不完美,至少有两个原因:
启用和不启用 SecurityManager 运行的 Java 应用程序有很大不同。这就是为什么它最终需要关闭,但不能用 System.setSecurityManager(null) 来完成。此调用将导致另一次安全权限检查,这将不可避免地失败,因为应用程序代码(SecurityManager 子类)位于调用堆栈的顶部。
所有Java应用程序都是多线程的,其他线程可以在forbidSystemExitCall()和enableSystemExitCall()之间执行各种操作。其中一些内容可以通过安全权限检查来保护,但由于与上述相同的原因,安全权限检查也会失败。如果重写 checkExit() 而不是 [更通用] checkPermission(),那么它将涵盖大多数情况。
(据我所知)解决此问题的唯一方法是将所有特权授予 SecurityManager 子类。它很可能需要由单独的类加载器加载,例如引导(空)类加载器。
Using SecurityManager to disallow System.exit() calls is not perfect, for at least 2 reasons:
Java applications running with and without SecurityManager enabled are very different. That's why it needs to be turned off eventually, but it cannot be done with System.setSecurityManager(null). This call will lead to another security permission check, that will inevitably fail, because application code (SecurityManager subclass) is on the top of the calling stack.
All the Java applications are multi-threaded, and other threads can do various things between forbidSystemExitCall() and enableSystemExitCall(). Some of these things can be protected with security permission checks, which will fail for the very same reasons as described above. If checkExit() is overridden instead of [much more generic] checkPermission(), it will cover most of the cases, though.
The only way (that I know) to resolve this is to grant all the privileged to the SecurityManager subclass. It will very likely require it to be loaded by a separate class loader, e.g. bootstrap (null) class loader.