4

我在 JBoss 5.1 中有一个 EJB3-Timer。 编辑: ShutdownHook 应该设置一个标志, doTimeOut() 可以优雅地终止(否则它将完成作业,并且在此计时器完成之前停止关机)。

@Stateless
class Timer {
    private static Thread hook;
    static {
       hook = new ShutdownHook();
    }
    @Timeout
    public void doTimeOut(){
       //some code
    }

    private class ShutdownHook implements Runnable(){

        Logger.getLogger(ShutdownHook.class.getName()).log(Level.INFO, "MyBEAN.ShutdownHook execute hook " + hook); // Not always printed to log
        Logger.getAnonymousLogger().log(Level.INFO, "MyBEAN.ShutdownHook execute hook " + hook); // throwns Exception
        System.out.println("MyBEAN.ShutdownHook execute hook " + hook);
        [...] // some code
    }
}

我找到了这两个帖子,但它们来自 2005 年,并且该错误被标记为 CLOSED:

http://www.pankaj-k.net/archives/2005/08/jboss_shutdown.html

http://jira.jboss.com/jira/browse/JBAS-2087

anonymousLogger 抛出的异常是 NullPointer:

2011-02-02 09:16:33,120 ERROR [STDERR] Exception in thread "Thread-33" 
2011-02-02 09:16:33,122 ERROR [STDERR] java.lang.NullPointerException
2011-02-02 09:16:33,122 ERROR [STDERR]  at org.apache.log4j.CategoryKey.<init>(CategoryKey.java:31)
2011-02-02 09:16:33,122 ERROR [STDERR]  at org.apache.log4j.Hierarchy.getLogger(Hierarchy.java:261)
2011-02-02 09:16:33,122 ERROR [STDERR]  at org.apache.log4j.Hierarchy.getLogger(Hierarchy.java:242)
2011-02-02 09:16:33,122 ERROR [STDERR]  at org.apache.log4j.LogManager.getLogger(LogManager.java:188)
2011-02-02 09:16:33,122 ERROR [STDERR]  at org.apache.log4j.Logger.getLogger(Logger.java:104)
2011-02-02 09:16:33,122 ERROR [STDERR]  at org.jboss.logbridge.LogBridgeHandler.publish(LogBridgeHandler.java:71)
2011-02-02 09:16:33,122 ERROR [STDERR]  at java.util.logging.Logger.log(Unknown Source)
2011-02-02 09:16:33,122 ERROR [STDERR]  at java.util.logging.Logger.doLog(Unknown Source)
2011-02-02 09:16:33,122 ERROR [STDERR]  at java.util.logging.Logger.log(Unknown Source)
2011-02-02 09:16:33,122 ERROR [STDERR]  at com.demo.MyBEAN$ShutdownHook.run(MyBEAN.java:202)

有任何想法吗?

4

2 回答 2

3

由于 Log4j 已关闭,记录器可能不可用,这显然发生在 JVM 关闭挂钩运行之前。如果您需要在关机时记录某些内容,我建议您使用 JBoss 机制,例如使用@PreDestroy

然后你的代码变成

@Stateless
class Timer {

    @Timeout
    public void doTimeOut(){
       //some code
    }

    @PreDestroy
    public void onShutdown() {

        Logger.getLogger(Timer.class.getName()).log(Level.INFO, "MyBEAN.ShutdownHook execute hook " + hook);
        [...] // some code
    }
}
于 2011-02-02T08:52:32.587 回答
1

我建议您阅读Java 中的 Shutdown Hooks?它们是如何使用的?

摘要:不能保证每次都执行关闭挂钩。它们是关闭机制的一部分,在您的情况下,您不应该真正使用它们来创建新对象,例如新的记录器。

我建议将计时器类中的记录器初始化为private static final Logger变量(通常这样做),然后在关闭挂钩中引用该实例。

但即便如此,您也不能 100% 确定它会运行(除非 JBoss 使用了一些诡计来保证这一点)。

于 2011-02-02T08:41:51.643 回答