这些 Java 8 官方挖的坑,你踩过几个?( 二 )


private static Object parseClassArray(int paramInt, ByteBuffer paramByteBuffer, ConstantPool paramConstantPool, Class<?> paramClass) {    Class[] arrayOfClass = new Class[paramInt];    int i = 0;    int j = 0;    for (int k = 0; k < paramInt; k++){        j = paramByteBuffer.get();        if (j == 99) {            // 注意这个方法         arrayOfClass[k] = parseClassValue(paramByteBuffer, paramConstantPool, paramClass);        } else {         skipMemberValue(j, paramByteBuffer);         i = 1;        }    }    return i != 0 ? exceptionProxy(j) : arrayOfClass;}private static Object parseClassValue(ByteBuffer paramByteBuffer, ConstantPool paramConstantPool, Class<?> paramClass) {    int i = paramByteBuffer.getShort() & 0xFFFF;    try    {        String str = paramConstantPool.getUTF8At(i);        return parseSig(str, paramClass);    } catch (IllegalArgumentException localIllegalArgumentException) {        return paramConstantPool.getClassAt(i);    } catch (NoClassDefFoundError localNoClassDefFoundError) {         // 注意这里 , 异常发生了转化        return new TypeNotPresentExceptionProxy("[unknown]", localNoClassDefFoundError);    } catch (TypeNotPresentException localTypeNotPresentException) {        return new TypeNotPresentExceptionProxy(localTypeNotPresentException.typeName(), localTypeNotPresentException.getCause());    }}【这些 Java 8 官方挖的坑,你踩过几个?】在 parseClassArray这个方法中 , 预期parseClassValue返回Class对象 , 但看实际parseClassValue的逻辑 , 在遇到NoClassDefFoundError时 , 返回的是TypeNotPresentExceptionProxy , 由于类型强转失败 , 最终抛出的是java.lang.ArrayStoreException:sun.reflect.annotation.TypeNotPresentExceptionProxy , 此时只能通过debug到这行代码 , 找到具体是缺少哪个类定义 , 才能解决这个问题 。
笔者重现一下发现这个坑的场景 , 有三个module , module3依赖module2但未声明依赖module1 , module2依赖module1 , 但声明的是optional类型 , 依赖关系图如下:

这些 Java 8 官方挖的坑,你踩过几个?

文章插图
 
上面每个module中有一个Class , 我们命名为ClassInModuleX 。ClassInModule3启动时在注解中使用了ClassInModule2的类 , 而ClassInModule2这个类的继承了ClassInModule1 , 这几个类的依赖关系图如下:
这些 Java 8 官方挖的坑,你踩过几个?

文章插图
 
如此 , 其实很容易知道在module运行ClassInModule3时 , 会出现ClassInModule1的NoClassDefFoundError的 , 但实际运行时 , 你能看到的异常将不是NoClassDefFoundError , 而是java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy , 此时 , 若想要知道具体是何许异常 , 需通过debug在AnnotationParser中定位具体问题 , 以下展示两个截图 , 分别对应系统控制台实际抛出的异常和通过debug发现的异常信息 。
控制台异常信息:
这些 Java 8 官方挖的坑,你踩过几个?

文章插图
 
注意异常实际在红色圈圈这里 , 自动收缩了 , 需要展开才可以看到通过debug发现的异常信息:
这些 Java 8 官方挖的坑,你踩过几个?


推荐阅读