Eclipse中的关闭挂钩无法正常工作

27

我通过以下方式添加了一个关闭挂钩

Runtime.getRuntime().addShutdownHook(myShutdownHook);

通常情况下它正常工作,但当我在Eclipse中点击红色停止按钮时就不行了。有没有办法让关闭挂钩在Eclipse中被调用?


该问题被标记为重复,与两年后提出的一个问题相同。 - urir
实际上,另一个是两年前的(09而不是11)。你可能把日子(13)看成了年份。 - Christoph142
6个回答

17

红色的停止按钮会强制终止应用程序,即不会优雅地关闭,因此JVM不知道应用程序正在退出,因此关闭挂钩(shutdown hooks)不会被调用。

不幸的是,在Windows中没有办法确保总是调用关闭挂钩的机制。这只是可能被调用的一些东西,但没有保证。


2
请引用一份来源,证明“没有办法提供一种机制来确保挂钩总是被调用”,因为页面http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)清楚地说明,当“程序正常退出”或“虚拟机响应用户/系统中断而终止”时,挂钩将会运行。 - Pacerier
1
@Pacerier,我的说法是基于我进行的一个测试,我关闭了运行批处理脚本调用Java应用程序的控制台窗口。在关闭窗口时,关闭挂钩没有被调用。 - Zoltán
3
这个例子以及从Eclipse停止应用程序是程序没有“正常退出”的例子。 - Zoltán

9

我通过将JavaProcess替换为装饰的进程来进行了黑客攻击:

    IProcess p = launch.getProcesses()[0];
    launch.addProcess(new JavaProcessDecorator(p));
    launch.removeProcess(p);

装饰器正在覆盖终止函数。

public class JavaProcessDecorator implements IProcess {

private IProcess p;

public JavaProcessDecorator(IProcess p) {
    this.p = p;
}

private boolean sigkill = false;

@SuppressWarnings("rawtypes")
@Override public Object        getAdapter(Class arg)                { return p.getAdapter(arg); }
...
@Override public ILaunch       getLaunch()                          { return p.getLaunch(); }
@Override public IStreamsProxy getStreamsProxy()                    { return p.getStreamsProxy(); }
@Override public void          setAttribute(String s1, String s2)   {        p.setAttribute(s1, s2); }
@Override public void          terminate() throws DebugException    {
    if(!sigkill) {
        try {
            IDebugIService cs = DirmiServer.INSTANCE.getRemote("main", IDebugIService.class);
            if(cs != null) cs.modelEvent(new TerminateRequest());
        } catch (RemoteException e) { }
        this.sigkill = true;
    } else p.terminate();
}}

首先点击红色按钮,我向应用程序发送一条消息请求温和终止。如果这不奏效,第二次点击红色按钮将强制关闭它。


2

我知道自己来晚了,但我在寻求帮助时发现了这个帖子,其他人可能也会这样。

我们遇到了同样的问题,并通过一个 Eclipse 插件(在Linux上)解决了它,该插件现在提供了额外的停止按钮。希望这对你们所有人都有用,就像它帮助我们一样 :)


可以通过Eclipse Marketplace轻松安装,从帮助菜单中找到(链接包含手动下载和安装的说明,但我在那里遇到了一些错误)。 - extremecoder85

0

红色的停止按钮只是终止应用程序,根据Eclipse开发人员的说法,他们无法对此做任何事情,请参见Eclipse错误跟踪器中的issue


0

如果你只是想测试这个钩子是否起作用,可以从触发点throw new RuntimeException()。即使在Eclipse中,这样也应该调用关闭钩子。


0
@Pacerier - 根据Javadoc:在极少数情况下,虚拟机可能会异常终止,也就是说,在不正常关闭的情况下停止运行。这种情况发生在虚拟机被外部终止时,例如在Unix上使用SIGKILL信号或在Microsoft Windows上使用TerminateProcess调用。如果本地方法出现问题,例如破坏内部数据结构或尝试访问不存在的内存,则虚拟机也可能会异常终止。如果虚拟机异常终止,则不能保证是否会运行任何关闭挂钩。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接