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类型 , 依赖关系图如下:
文章插图
上面每个module中有一个Class , 我们命名为ClassInModuleX 。ClassInModule3启动时在注解中使用了ClassInModule2的类 , 而ClassInModule2这个类的继承了ClassInModule1 , 这几个类的依赖关系图如下:
文章插图
如此 , 其实很容易知道在module运行ClassInModule3时 , 会出现ClassInModule1的NoClassDefFoundError的 , 但实际运行时 , 你能看到的异常将不是NoClassDefFoundError , 而是java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy , 此时 , 若想要知道具体是何许异常 , 需通过debug在AnnotationParser中定位具体问题 , 以下展示两个截图 , 分别对应系统控制台实际抛出的异常和通过debug发现的异常信息 。
控制台异常信息:
文章插图
注意异常实际在红色圈圈这里 , 自动收缩了 , 需要展开才可以看到通过debug发现的异常信息:
推荐阅读
- Alibaba开源Java诊断工具Arthas简单介绍
- 14个 JavaScript 代码优化技巧
- 雕刻|投资翡翠饰品有窍门,作为新手收藏者,掌握这些知识就够了
- 春天来峨眉山,这些地方别错过哦!
- 水星两极地区有一些陨石坑,研究发现这些坑内 火星的地形兼具充满陨石坑
- 31 道 Java 核心面试题,统统打包给你
- 口气太重引人捂鼻?多喝这些茶让口气变清新
- SSHJ - 功能齐全的Java SSH库
- 一 「JAVA」两个数组的交集—力扣每日一题
- Java程序员对领域驱动设计的思考与认知