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

但是我不能使它工作。 我尝试使用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中会发生什么? 仅考虑最后一个处理程序吗?

===============>>#1 票数:1 已采纳

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

 (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线程启动它还是将来使用它都无关紧要。

  ask by Cedric Martin translate from so

未解决问题?本站智能推荐:

1回复

线程的DefaultUncaughtExceptionHandler无法捕获AlertDialog onClick()方法中引发的异常

我设置默认UncaughtExceptionHandler在我当前线程Activity的onCreate()和抛出RunTimeException从我的AlertDialog的onClick()监听器,但异常没有被捕获。 我还尝试从onCreateOptionsMenu()和onOptions
2回复

按钮附加示例

我试图通过按钮button.append("now")将文本添加到按钮名称中,例如按钮“ ButtonName”为“ ButtonNameNow”,这会button.append("now")未捕获的异常 是否有任何示例或原因导致我搜索到该内容,例如搜索一无所获,我也不了解有关Button
1回复

C ++异常处理-具体示例

我有这个程序(部分程序未发布): 如果出现以下情况,我想终止程序:-文件未打开; -由getline获得的标头字符串不等于“ String”; -任何读取功能失败; -任何搜索失败; -strid,与1234不匹配。 如何使用C ++异常执行此操作? 我应该使用单个try
1回复

为什么Clojure核心库使用具体的派生?

在Clojure的类型机制的文档中 ,有人说 具体推导是坏事 你不能从具体类,只有接口派生数据类型 但是,一些核心Clojure类使用具体派生(还有其他示例,但这些是超类属于clojure.lang的唯一情况): ARef扩展了
1回复

如何提升更具体的组规格?

这是一个托盘( https://github.com/pallet )问题。 目前,我尝试对电梯操作使用更具体的组规范。 我尝试在小组中仅提升一个特定节点(例如,一个新节点): 如此处所述: http : //palletops.com/pallet/api/0.8/pallet.a
2回复

project.clj:dependencies具体做什么,它们是必需的吗?

我问这个问题是为了消除我对project.clj:dependencies和使用:use /:require指定的模块的困惑。 我用莱恩建造。 我想编写一个Clojure项目,也许除了依赖特定的Clojure版本之外,不希望该项目依赖于任何模块的特定版本。 例如: 我并不需
7回复

Clojure For Comprehension示例

我正在使用docjure ,它的select-columns函数需要一个列映射。 我想抓住我的所有列而不必手动指定它。 如何生成以下作为惰性无限向量序列[:A:B:C:D:E ...:AA:AB:AC ....:ZZ ......:XFD]?
3回复

在Clojure函数中重新绑定var的具体缺点是什么?

在探索Clojure中计算阶乘的各种方法时,我提出了以下(非惯用)函数: (defn factorial-using-do-dotimes [x] (do (def a 1) (dotimes [i x] (def a (* a (inc i))))) a)
2回复

如何在Clojure中使用具体类型参数实现接口?

我正在尝试使用Clojure的AWS Lambda。 这是有效的Java代码: 这是Clojure代码,不起作用。 在两个类上都使用Javap: Java的: Clojure的: 我想知道用具体的返回类型实现接口的最佳方法是什么。 AWS使用当前代码抱怨
1回复

Clojure vs. Lisp:为什么在Clojure中没有具体的虚线对? [关闭]

在这个讨论中,海报(mikera)说: Clojure中没有虚线对。 这样做的哲学原因是Clojure避免使用具体的“对”数据结构,而是强调可能具有具体实现方式的抽象“序列”。 有人可以详细说明或指向我一些有关这意味着什么的文献吗? 这是更优雅还是数学上更纯粹的方法?