我正在尝试添加对信号的支持(尤其是对Ctrl C)。我的工具是用Java编写的,当Ctrl C
被捕获时,我想执行清理。我的主文件是应用程序,代码和平如下:
if (ArgDefinitions.getInstance().hasOption(ArgNames.EXECUTE)) {
performShutdownHooks();
preformRun();
}
应用程序解析用户的选项并运行适当的方法。因此,当用户使用“执行”选项并单击Ctrl C时,我希望程序停止并清理该区域。为了处理信号,我添加了performShutdownHooks方法,如下所示:
private void performShutdownHooks() {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
performCleanup();
}
});
}
它做我想做的——如果我运行工具并在它运行时杀死它,它会进行清理(它在后台运行一个特殊的命令)。当我不停止它时,问题就出现了。我得到以下例外:
Exception in thread "Thread-2" java.lang.IllegalStateException: Job manager has been shut down.
at org.eclipse.core.internal.jobs.JobManager.schedule(JobManager.java:1104)
at org.eclipse.core.internal.jobs.InternalJob.schedule(InternalJob.java:427)
at org.eclipse.core.runtime.jobs.Job.schedule(Job.java:436)
at glichautil.CommandExecutor.runCommandInBackground(CommandExecutor.java:134)
at glicha.core.Application.performCleanup(Application.java:869)
at glicha.core.Application.access$0(Application.java:838)
at glicha.core.Application$1.run(Application.java:985)
我认为performShutdownHooks在最后运行,尽管我没有试图杀死它。可能是其他东西杀死了它,但它不应该这样做,因为如果我注释掉方法调用performShutdownHooks(),它会正常工作(不会引发任何异常)。这让我相信,出于某种原因,即使我没有按Ctrl C,performShutdownHooks方法仍在运行。为了解决这个问题,我需要向performShutdownHooks方法添加什么吗?也许我错过了一些关于addShutdownHook的内容?如果这是对问题的正确解释,那么我认为如果我能在最后以某种方式取消它的运行,那么它就会解决问题。也可能是代码中使用的其他线程正在被杀死,并且出于某种原因执行该方法。
编辑:我想我已经设法理解了它为什么这样工作。在输入我的Shutdown Hooks
方法之前,它打印:
Job found still running after platform shutdown.
Jobs should be canceled by the plugin that scheduled them during shutdown: glicha.testmanager.HandleParallelJobs.
我想,这就是调用关闭钩子的原因。问题是,我不知道如何解决它。我从文件中读到:
Java虚拟机关闭以响应两种事件:
>
当最后一个非守护进程线程退出或调用exit(相当于System.exit)方法时,程序正常退出,或者
虚拟机被终止,以响应用户中断,例如键入Ctrl,或系统范围内的事件,例如用户注销或系统关闭。
所以我想,当插件关闭时,它会调用ShutdownHooks(如果我错了,请纠正我)。问题是我不明白如何区分这两种可能性。我只想捕捉信号并执行清理,但我不想在其中一个VM关闭时这样做。我该如何处理这个问题?
您可以覆盖SecurityManager
check Exit(int status)
方法-如果在任何地方显式调用System.exit(status)
,则此方法有效-但是,当应用程序“正常”退出(没有活动线程)或错误杀死VM时,它不会设置状态。
System.setSecurityManager(new ExitMonitorSecurityManager());
Runtime.getRuntime().addShutdownHook(new Thread(new MyShutdownHook()));
private static class ExitMonitorSecurityManager extends SecurityManager {
@Override
public void checkPermission(Permission perm) {
//Something;
}
@Override
public void checkPermission(Permission perm, Object context) {
//Something
}
@Override
public void checkExit(int status) {
System.out.println("Setting exit value via security manager...");
MyShutdownHook.EXIT_STATUS = status;
}
}
private static class MyShutdownHook implements Runnable {
public static Integer EXIT_STATUS;
public void run() {
System.out.println("In MyShutdownHook - exit status is " + EXIT_STATUS);
}
}
关闭挂钩的常见问题之一是没有保证关闭事物的顺序。我假设在您的情况下,调度
框架可能已经有了自己的关闭挂钩,它已经执行了清理(停止任务)。
与shutdown hook相关的javadoc在某种程度上解释了您不能依赖其他资源的存在,因为它们可能已经被关闭了。
现在,当您尝试在关闭挂钩中执行此操作时,您可能会收到上述错误,具体取决于关闭挂钩的执行顺序。
这并不是你真正想要的,但我想你可能一点问题都没有。我宁愿就以下事情进行讨论
您可能希望将清理时运行的代码添加到您的问题中。根据我掌握的信息,您可能希望关闭已经关闭的东西。
如果你仍然想做一些信号拦截,实际上有一种方法,但我不推荐。根据这个链接,https://www.javaspecialists.eu/archive/Issue043.html,您可以使用太阳的信号类。其他。*包裹
太阳。misc包只包含非官方的API,这些API可能会被删除,恕不另行通知。似乎没有官方API支持您的用例(至少据我所知)。
嘿StackOverflow社区, 关于抛出异常。一般什么时候抛出和异常,什么时候抓取? 假设我遇到了这样的情况,我不得不退出,因为发生了一些问题,我无法从它中恢复过来。我是投还是接? 我现在就这么做: 这样做对吗?如果我只是抛出异常会更合适吗?对不起,我是例外的新手:)
本文向大家介绍JAVA异常处理捕获与抛出原理解析,包括了JAVA异常处理捕获与抛出原理解析的使用技巧和注意事项,需要的朋友参考一下 JAVA 异常 当代码运行出现错误导致程序终止运行或出现错误情况的状况,就是异常。异常不是指语法错误,即不属于编译错误,只有运行的程序才会有异常。 这个时候,JAVA 就提供了优秀的处理方法:异常处理 异常处理能让程序在异常发生时,按照异常处理设定的逻辑对异常进行处理
问题 你想捕获一个异常后抛出另外一个不同的异常,同时还得在异常回溯中保留两个异常的信息。 解决方案 为了链接异常,使用 raise from 语句来代替简单的 raise 语句。 它会让你同时保留两个异常的信息。例如: >>> def example(): ... try: ... int('N/A') ... except ValueError as e:
"CATCH"应该严格地在"扔"之后叫吗?" 例1: 错误: 找不到方法“接收器”:没有方法缓存,也没有^在/tmp/739536251/main块中查找_方法。pl6第11行 例2: 无误
问题 你在一个 except 块中捕获了一个异常,现在想重新抛出它。 解决方案 简单的使用一个单独的 rasie 语句即可,例如: >>> def example(): ... try: ... int('N/A') ... except ValueError: ... print("Didn't work") ...
前几天,我在我们的一个项目中看到一些代码,它们使用try-catch并重新抛出捕获的异常,如下所示: 除了catch块中的异常之外,没有做任何其他操作,所以我甚至不确定它为什么会被抛出。我看不出再次抛出同一个异常并对该异常不做任何处理有什么好处。 如果重新抛出catch块中捕获的异常,C#如何处理?它是否陷入了无限抛接球循环?还是说它最终会放弃试一试?