设为首页 加入收藏

TOP

深入Spring Boot: 怎样排查 java.lang.ArrayStoreException(三)
2018-03-11 09:11:29 】 浏览:2282
Tags:深入 Spring Boot: 怎样 排查 java.lang.ArrayStoreException
rg.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration
  • cause是 java.lang.ClassNotFoundException: org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration
  • 终于真相大白了,是找不到org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration这个类。

    那么它是怎么变成ArrayStoreException的呢?

    仔细看下代码,可以发现AnnotationParser.parseClassValue把异常包装成为Object

    //sun.reflect.annotation.AnnotationParser.parseClassValue(ByteBuffer, ConstantPool, Class<?>)
        private static Object parseClassValue(ByteBuffer buf,
                                              ConstantPool constPool,
                                              Class<?> container) {
            int classIndex = buf.getShort() & 0xFFFF;
            try {
                try {
                    String sig = constPool.getUTF8At(classIndex);
                    return parseSig(sig, container);
                } catch (IllegalArgumentException ex) {
                    // support obsolete early jsr175 format class files
                    return constPool.getClassAt(classIndex);
                }
            } catch (NoClassDefFoundError e) {
                return new TypeNotPresentExceptionProxy("[unknown]", e);
            }
            catch (TypeNotPresentException e) {
                return new TypeNotPresentExceptionProxy(e.typeName(), e.getCause());
            }
        }

    然后在sun.reflect.annotation.AnnotationParser.parseClassArray(int, ByteBuffer, ConstantPool, Class<?>)里尝试直接设置到数组里

    // sun.reflect.annotation.AnnotationParser.parseClassArray(int, ByteBuffer, ConstantPool, Class<?>)
    result[i] = parseClassValue(buf, constPool, container);

    而这里数组越界了,ArrayStoreException只有越界的Object的类型信息,也就是上面的

    java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy

    解决问题

    发现是java.lang.ClassNotFoundException: org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration,则加上@ConditionalOnClass的检查就可以了:

    @Configuration
    @AutoConfigureBefore(EndpointAutoConfiguration.class)
    @AutoConfigureAfter(HealthIndicatorAutoConfiguration.class)
    @ConditionalOnClass(value = {HealthIndicator.class, EndpointAutoConfiguration.class})
    public class MyHealthIndicatorAutoConfiguration {

    准确来说是spring boot2把一些类的package改了:

    spring boot 1里类名是:

    • org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration

    spring boot 2里类名是:

    • org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration

    总结

    • 当类加载时,并不会加载它的annotation的field所引用的Class<?>,当调用Class.getDeclaredAnnotation(Class<A>)里才会加载

      以上面的例子来说,就是@AutoConfigureBefore(EndpointAutoConfiguration.class)里的EndpointAutoConfiguration并不会和MyHealthIndicatorAutoConfiguration一起被加载。

    • jdk内部的解析字节码的代码不合理,把ClassNotFoundException异常吃掉了
    • 排查问题需要一步步深入调试
    首页 上一页 1 2 3 下一页 尾页 3/3/3
    】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
    上一篇MySQL 系统变量配置基础 下一篇使用Java函数接口及lambda表达式..

    最新文章

    热门文章

    Hot 文章

    Python

    C 语言

    C++基础

    大数据基础

    linux编程基础

    C/C++面试题目