Handler.publish() 的实现可以抛出运行时异常吗?



我有一个关于java.util.logging.Handler的问题:

是否允许此抽象方法的实现抛出运行时异常,还是应始终向错误管理器报告?

文档没有指定,但类中的其他方法明确说明了它们可以抛出的内容:

公共摘要无效发布(日志记录记录) 发布日志记录。 日志记录请求最初是向 Logger 对象发出的,该对象 初始化日志记录并将其转发到此处。

处理程序负责格式化消息,何时以及是否 必要。格式应包括本地化。

参数:记录 - 日志事件的描述。空记录是 静默忽略且未发布

[链接: https://docs.oracle.com/javase/7/docs/api/java/util/logging/Handler.html#publish(java.util.logging.LogRecord)]

在这种情况下,API 规范并不总是与实现匹配。 源代码中不成文的规则似乎是:

  1. 对空记录的处理可以是恶意的或忽略的。 StreamHandler 的子类忽略 null,并且 MemoryHandler 是 null 敌对的。 记录器从不传递 null 进行发布,JDK-8216363:java.util.logging.Handler#isLoggable 中的 NullPointerException 使其将空记录视为忽略。
  2. 从 isLoggable 引发的任何运行时异常都将转义处理程序。 这意味着从筛选器引发的任何异常都会转义发布方法,并且不会被错误管理器捕获。 请注意,没有枚举ErrorManager.FILTER_FAILURE,这意味着该行为是有意的。
  3. 发布不应引发的异常在错误管理器文档中枚举。 大多数情况是格式和写入错误。

真正的发布应该委托给错误管理器,以确定发布是否引发异常。 来自 Handler.setErrorManager 文档:

如果在使用此处理程序时发生任何错误,将调用错误管理器的"错误"方法。

这意味着发布应该服从错误管理器的行为,默认情况下不会抛出错误管理器。

如果你想通过Handler.reportError获得异常,你必须使用偷偷摸摸的抛出。

public class HostileErrorManager extends ErrorManager {
    public HostileErrorManager() {
    }
    @Override
    protected void reportError(String msg, Exception ex, int code) {
        sneakyThrow(new Throwable(msg + ": " + code, ex));
    }
    @SuppressWarnings("unchecked")
    private <T extends RuntimeException> void sneakyThrow(Throwable t) throws T {
        throw (T) t;
    }
}

最新更新