转载

聊聊幽灵Class

起因

偶然一次路过同事电脑,看着黑底蓝色满屏的堆栈信息,过去笑着拍了拍他的肩膀说道「小哥,又在写BUG呢」凑过去仔细看了一眼异常堆栈详情,「虎躯一震」哟,高端的,这堆栈后面的还有类的包路径信息呢呢,以前看堆栈的时候咋没有特别注意

坐下打开电脑翻看了下一下Logback的代码核心计算逻辑 ch.qos.logback.classic.spi.PackagingDataCalculator

聊聊幽灵Class

获取 Package 下的 MANIFEST.MF 文件里面 Implementation-Version 信息

聊聊幽灵Class

和获取类所在的 jar 包路径

可以看到所有的信息都在类对应的Class对象上

深入思考

很多时候为了解决Maven扁平化依赖臃肿和依赖冲突问题,我们往往会用上类隔离框架,比如说支付宝开源的 sofa-ark ,其基本原理就是使用单独的 ClassLoader 加载,并且将一部门类 EXPORT ,假设如果遇到没有被 EXPORT 出来的类(幽灵Class),会发生什么情况呢?

分析

因为是属于没有被 EXPORT 出来的类所以最终会委托给应用类加载器加载

聊聊幽灵Class

聊聊幽灵Class

为了防止重复加载,所以应用类加载器在加载类的时候会根据加载的 className 加锁,因为类也不是应用类加载器加载的所以会进行双亲委派加载,最后抛出 ClassNotFoundException ,再结合 PackagingDataCalculator 对异常的处理

聊聊幽灵Class 程序不会终止,所以我们可以得出结论只要碰到「幽灵Class」 logback 都会重新把类按照双亲委派的方式加载一遍。

有锁的地方就会有锁竞争,并且 Class.load 也是一个耗时的过程,所以同一个 ClassName 如果并发出现在日志堆栈中势必会导致一部分线程会 block ,这对于线上系统中简直就是灾难.

改进

在最近的logback版本中并没有发现对 ClassNotFoundException 的类做特殊处理,并且正如 logback 官方说的

While useful, packaging data is expensive to compute, especially in applications with frequent exceptions.

所以只要logback的版本大于1.1.3,packageDate这个配置默认都是关闭的

https://logback.qos.ch/manual...
原文  https://segmentfault.com/a/1190000018637595
正文到此结束
Loading...