繁体   English   中英

defaultUncaughtExceptionHandler的具体示例

[英]Concrete example of a defaultUncaughtExceptionHandler

我有几次遇到这样的情况:期货中的异常情况很难被追查(并且在这里已经问过一个问题,为什么某些异常情况似乎永远不会发生,并且这个问题不是我以前的问题的重复),因此决定尝试设置“默认未捕获的异常处理程序”。

但是我不能使它工作。 我尝试使用reify,并尝试使用代理。 好像什么也没发生。

这是重现此问题的最小案例:

REPL> (Thread/setDefaultUncaughtExceptionHandler
  (proxy [Thread$UncaughtExceptionHandler] []
    (uncaughtException [thread throwable]
      (do (println (-> throwable .getCause .getMessage))
          ; (error "whatever...") ; some 'timbre' logging if you have timbre
      ))))
nil
REPL> (future (do (Thread/sleep 100) (/ 0 0)))
#<core$future_call$reify__6267@c2909a1: :pending>
REPL>

我尝试了println ,尝试了使用音色记录到文件,尝试了将其吐到临时文件,并尝试通过取消引用来强制将来运行...显然,从未调用默认的未捕获异常处理程序。

谁能给我展示一个交互式/ REPL示例,它说明一个正在工作的默认未捕获异常处理程序实际上是在捕获异常吗?

一个额外的问题是:一旦设置了默认的未捕获异常处理程序,是否有一种简单的方法可以“看到”它的设置? 当您测试该功能并多次调用setDefaultUncaughtExceptionHandler时,REPL中会发生什么? 仅考虑最后一个处理程序吗?

期货并非如此。 异常不会逃逸。

 (deref (future (do (Thread/sleep 100) (/ 0 0))))

 ExecutionException java.lang.ArithmeticException: Divide by zero
    java.util.concurrent.FutureTask.report (FutureTask.java:122)
    java.util.concurrent.FutureTask.get (FutureTask.java:192)
    clojure.core/deref-future (core.clj:2108)
    clojure.core/future-call/reify--6267 (core.clj:6308)
    clojure.core/deref (core.clj:2128)

Java的FutureTask.run()的核心是答案...

boolean ran;
try {
    result = c.call();
    ran = true;
} catch (Throwable ex) {
    result = null;
    ran = false;
    setException(ex);
}

这为最终的响应者节省了问题。 如果我们稍微重新构造测试用例,我们可以清楚地看到异常处理程序的工作:

(Thread/setDefaultUncaughtExceptionHandler
    (proxy [Thread$UncaughtExceptionHandler] []
      (uncaughtException [thread throwable]
        (do (println "****" (-> throwable .getMessage))
        ))))

我删除了getCause,因为我们不一定要拥有一个...

(.start (Thread. #(/ 0 0)))

标准品产量...

**** Divide by zero

如果您所需要的(如您的注释所建议)是具有适当异常处理程序的线程,请考虑以下内容:

(defn exception-safe-queue-reader [source sink]
    (try
        (let [message (source)]
            (sink message))
        (catch Throwable t
            (println "****" t))
    (recur source sink))

(对我而言)这是比使用uEH更标准的Java习惯用法-即,如果您要处理错误,请直接在代码中处理它们。 使用裸Java线程启动它还是将来使用它都无关紧要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM