1

我正在尝试进行干净而优雅的关机,但由于某种原因,它不会执行。我试过了:

sys addShutdownHook{
    logger.warn("SHUTTING DOWN...")
    // irrelevant logic here...
}

并且:

Runtime.getRuntime.addShutdownHook(ThreadOperations.delayOnThread{
        logger.warn("SHUTTING DOWN...")
        // irrelevant logic here...
    }
)

其中ThreadOperations.delayOnThread定义是:

object ThreadOperations {

    def startOnThread(body: =>Unit) : Thread = {
        onThread(true, body)
    }

    def delayOnThread(body: =>Unit) : Thread = {
        onThread(false, body)
    }

    private def onThread(runNow : Boolean, body: =>Unit) : Thread = {
        val t=new Thread {
            override def run=body
        }
        if(runNow){t.start}
        t
    }

    // more irrelevant operations...
}

但是当我运行我的程序(可执行jar,双重激活)时,钩子没有启动。那我做错了什么?在 scala 中添加关闭挂钩的正确方法是什么?它与我使用双重激活的事实有任何关系吗?

双重激活是这样完成的:

object Gate extends App {
    val givenArgs = if(args.isEmpty){
                        Array("run")
                    }else{
                        args
                    }

    val jar = Main.getClass.getProtectionDomain().getCodeSource().getLocation().getFile;
    val dir = jar.dropRight(jar.split(System.getProperty("file.separator")).last.length + 1)
    val arguments = Seq("java", "-cp", jar, "boot.Main") ++ givenArgs.toSeq
    Process(arguments, new java.io.File(dir)).run();
}

(scala 版本: 2.9.2 )谢谢。

4

2 回答 2

0

在您的第二次尝试中,您的关闭挂钩似乎只是创建了一个线程而从未启动它(因此它只是收集垃圾并且什么都不做)。我错过了什么?(编辑:是的,我做了,见评论。我的错)。

在第一次尝试中,问题可能只是底层日志有一些缓存,并且应用程序在日志刷新之前退出。

于 2012-09-10T10:48:33.767 回答
0

解决了。

出于某种原因,我认为这run!分离过程相反。它实际上会挂起,因为有开放的流留给Process,这是从返回的run(或者它可能只是因为另一个原因而挂起,因为exec没有挂起,而是返回一个Process带有开放流的子进程,就像run) . 由于这个原因,原来的进程还活着,我不小心给它发送了信号。当然,它不包含处理程序或关闭挂钩,所以什么也没发生。

解决方案是使用Runtime.getRuntime.exec(arguments.toArray)而不是Process(arguments, new java.io.File(dir)).run();,关闭Gate对象中的流,并将 ^C 信号发送到正确的进程。

于 2012-09-10T11:58:56.287 回答