如何处理瞬态类加载错误,例如线程中断
Posted
技术标签:
【中文标题】如何处理瞬态类加载错误,例如线程中断【英文标题】:How to handle transient Class Loading error such as thread interrupt 【发布时间】:2019-11-13 22:25:30 【问题描述】:所以我有一个ClassLoader
后代,它通过网络加载所需的类。如何正确处理瞬态错误(如临时网络中断)或线程中断超时?
这里的问题是,我唯一能从loadClass()
中扔掉的是ClassNotFoundException
。一旦抛出 CNFE,JVM 似乎不会重新尝试加载类,而是会从 java 代码中触发 NoClassDefFoundError
。
这是合乎逻辑的,但不考虑暂时性错误。如果我们从类加载器中抛出 CNFE,则意味着该类将永远不可用并且代码将永远无法正常工作,即使问题已解决并且可以在重试时加载类。类加载代码的长时间等待是不可取的,而且并非总是可能的。
更糟糕的是,类加载器可能会被中断。它会在网络操作等待时导致 InterruptedException,这反过来又需要抛出 CNFE,再次导致无法使用的状态,即没有加载完美的类并且永远不会加载并且代码被破坏。
这里有关于如何处理瞬态类加载失败的推荐解决方案吗?我更希望代码获得一次ClassNoDefFoundError
,但下次需要时重试。
基本上我有两个想法:
我们可以将类加载器标记为坏,一旦它出现瞬时错误,逐步停止使用并创建一个新的,它可能会重新尝试加载此类。 (甚至更不完整)我们可以从线程中清除中断标志并等待类加载完毕,然后恢复线程上的中断标志。也许我什至错了,JVM 通常不应该抛出 NoClassDefFoundError
而不每次都去类加载器?
【问题讨论】:
【参考方案1】:这里的问题是,我唯一能从 loadClass() 中抛出的东西是 ClassNotFoundException
您是否尝试过抛出一些未经检查的异常?想知道 VM 将如何处理它。
我希望代码获得一次
ClassNoDefFoundError
,但有一个 下次需要时重试
因此,只要其他线程重试该类,由于ClassDefNotFoundError
(注意Error
后缀...),任意(数量)线程在任意点中止就可以了稍后加载?
似乎ClassDefNotFoundError
(也顾名思义)被认为是不可恢复的,这对大多数应用程序来说都是有意义的。
【讨论】:
好吧,当您有运行任务的应用程序时,错误将终止一项任务,但不会导致整个应用程序关闭。在大型系统中,ClassDefNotFoundError
绝对不是一个炫技。
@alamar 实际上,它不是一个显示停止器,如果应用程序准备处理这些异常。在这些情况下,通常会显式地(Class.forName(...)
,...)加载类,并且会适当地处理此失败。但是由于某些类加载错误基本上可能发生在代码中的任何地方,因此普通应用程序不准备在理论上可能发生的每个点尝试从该错误中恢复。
嗯,你通常在堆栈底部有一个大的捕获网,它将处理此类错误并将整个任务排队等待后续重试或失败。 Class.forName() 的问题是它的大部分依赖都是延迟加载的,它们仍然可以在任何地方拍摄。以上是关于如何处理瞬态类加载错误,例如线程中断的主要内容,如果未能解决你的问题,请参考以下文章