静态方法抛出运行时异常导致反射生成实例失败

简介: 静态方法抛出运行时异常导致反射生成实例失败

静态方法抛出运行时异常导致反射生成实例失败

文章目录

场景还原

1. 启动时,static属性获取时便打印了异常,不过没有注意到。
2. 之后在异常无法捕获之处既无正常往下走到return,也没有被Catch捕获异常,甚至在该行无法Step in进入debug,最终被外层的finally块处理。

生成实例失败的类

public class InnerPositionThread extends MonitorThread {
    Logger logger = LoggerFactory.getLogger(getClass());
    private static Map<String, List<BlockField>> blockAttrCfg = BlockUtils.getBlocks("innerposition.xml");
}

抛出运行时异常的方法

public class BlockUtils {
    public static Map<String, List<BlockField>> getBlocks(String templateName) {
        try {
            // do something
            }
        } catch (Exception var14) {
            var14.printStackTrace();
            throw new RuntimeException(var14);
        }
    }

无法捕获异常之处

try {
  Object monitor;
    // 下面这行将会异常
  monitor = (IfMonitor)Class.forName(mClass).newInstance();
  return null;
} catch (Exception var4) {
  log.error("启动监视器失败 " + config.getName() + " (" + monitorKey + ")", var4);
  return getStartFalseResponse(config, monitorKey, isCreate ? "监视器已建立,激活失败" : "启动监视器失败");
}

重试

另起工程简化示例进行查看原因。

接口

public interface InterfaceA {
    void functionA();
}

静态属性初始化抛出异常

public class ClassImplA implements InterfaceA {
    private static Logger logger = LoggerFactory.getLogger(ClassImplA.class);
    private static Long staticProperties = initStaticProperties();
    private static Long initStaticProperties() {
        throw new RuntimeException("ClassImplA throw runtime exception");
    }
    @Override
    public void functionA() {
        logger.info("function A be called!");
    }
}

测试main方法

public static void main(String[] args) {
        logger.info("start main");
        Object classAImpl;
        String className = ClassImplA.class.getName();
        logger.info("start get class A");
        try {
            classAImpl = (InterfaceA)Class.forName(className).newInstance();
            ((InterfaceA)classAImpl).functionA();
        } catch (Exception e) {
            logger.error("catch exception反射失败" + e.getMessage());
        } catch (Error e) {
            logger.error("catch error反射失败" + e.getMessage());
        } finally {
            logger.info("in finally end get class A");
        }
        logger.info("end main");
    }

测试输出

六月 02, 2020 2:34:52 下午 forname.MainTest main
信息: start main
六月 02, 2020 2:34:52 下午 forname.MainTest main
信息: start get class A
六月 02, 2020 2:34:52 下午 forname.MainTest main
严重: catch error反射失败null
六月 02, 2020 2:34:52 下午 forname.MainTest main
信息: in finally end get class A
六月 02, 2020 2:34:52 下午 forname.MainTest main
信息: end main

观察捕获到Error,而非Exception,打印堆栈可见,其最终抛出的错误是ExceptionInInitializerError。

java.lang.ExceptionInInitializerError
  at java.lang.Class.forName0(Native Method)
  at java.lang.Class.forName(Class.java:264)
  at forname.MainTest.main(MainTest.java:16)
Caused by: java.lang.RuntimeException: ClassImplA throw runtime exception
  at forname.ClassImplA.initStaticProperties(ClassImplA.java:12)
  at forname.ClassImplA.<clinit>(ClassImplA.java:9)
  ... 3 more

通过查看该类的继承发现ExceptionInInitializerError继承LinkageError,再继承Error,最终继承Throwable,所以该ExceptionInInitializerError不会被Exception的catch块捕获。

结论

通过请教他人得知:

  1. 这类Error必须干掉,不能带进程序,
  2. static属性初始化也不允许抛出异常,
  3. catch块也不能去抓取error或者Throwable的错误。
目录
相关文章
|
7月前
|
算法 编译器 C语言
【C++ 异常】C++ 标准库异常类及其应用
【C++ 异常】C++ 标准库异常类及其应用
82 0
|
7月前
|
Java C++ Spring
解决NoUniqueBeanDefinitionException异常的方法
了解Spring框架中`NoUniqueBeanDefinitionException`异常的原因和解决方案。此异常发生在容器内有多个相同类型的bean时,Spring无法决定注入哪个bean。解决方法包括:使用`@Primary`注解标记首选bean,利用`@Qualifier`注解配合`@Autowired`、`@Resource`、`@Inject`或`@Value`指定bean名称。选择哪种方法取决于业务需求和具体场景,预防措施是避免创建多个同类型bean或使用`@Primary`注解。
247 0
|
27天前
|
Java Android开发
如何确定抛出`NoSuchFieldError`异常的字段
当Java程序运行时,如果尝试访问一个不存在的字段,就会抛出`NoSuchFieldError`异常。要确定引发此异常的字段,可以通过检查异常堆栈跟踪中的类名和字段名来定位问题所在。此外,确保所使用的类版本一致,避免因类文件不匹配导致的此类错误。
107 7
|
6月前
|
Java
ClassCastException(类转换异常)可能原因和解决方法总结
ClassCastException(类转换异常)可能原因和解决方法总结
|
7月前
|
Java 开发者
Java中的受检异常和非受检异常的区别
Java中的受检异常和非受检异常的区别
|
7月前
|
Java 索引
JAVA异常类及其主要方法
JAVA异常类及其主要方法
253 3
|
7月前
|
Java
Java异常的抛出
Java异常的抛出
31 0
|
Java 开发者
JAVA异常类异常抛出处理
JAVA异常类异常抛出处理
136 0
【异常机制】异常抛出变量的生命周期
【异常机制】异常抛出变量的生命周期
73 0
【异常机制】异常抛出变量的生命周期
|
Java 编译器
Java中的异常(抛出异常、自定义异常等)
Java中的异常(抛出异常、自定义异常等)
314 1