一、背景
目前工作中遇到2个情况因为捕获的是Exception而不是Error,导致程序无法正常运行。
1、使用google的ortools库(jni):因为和操作系统相关,需要判断运行环境是否兼容,如果不兼容,则不使用ortools库,而使用常规java库处理。判断的代码会抛出Error,需要catch Throwable。
2、使用自定义类加载器,做插件,抛出java.Lang.LinkageError,而程序捕获的是Exception。Error导致定时线程退出,处理程序变成“幽灵”,具体现象是:插件无法更新,且没有任何错误日志。
二、分析
通常建议程序只捕获Exception,而不捕获Error,后者是可以避免的,不应该是程序去处理。但特殊场景下,还是需要捕获Error,即catch Throwable,让人知道程序中发生什么问题。
顺便记录一下:
java.Lang.LinkageError 这个异常在使用多ClassLoader的应用程序时常常会遇到,但是具体它是怎么产生的,很少人能够回答上来,于是上来来一发。
描述一下碰到这个异常的场景:应用A中使用了自定义的classLoader来加载所属应用的多个插件,以便能使各插件包达到类隔离的效果,每个插件都依赖了应用A中提供的一个依赖包M,这个依赖包在应用A中是有加载的,一般情况下,只要组件的依赖中打包时去除掉这个依赖包M,就不会有问题。但是实际的操作中,有的插件开发者经常会有意无意的将排除这个事情忘记。当把包含了依赖包M的插件发布到应用A中时,就可能出现这个异常。提示:java.lang.LinkageError.
这个错误发生的原因是同一个限定名的class类被多个不同的ClassLoader加载后,相互交叉使用导致的类冲突的情况。同一个限定名的class在不同的classLoader中属于不同的 Class实例,而JVM在加载某一个类时,需要加载所有import进入的Class,这种情况下,如果自定义的classLoader中存在与parentClassLoader需要加载相同限定名的Class时,就会抛出java.Lang.LinkageError.