起因
偶然一次路过同事电脑,看着黑底蓝色满屏的堆栈信息,过去笑着拍了拍他的肩膀说道「小哥,又在写BUG呢」凑过去仔细看了一眼异常堆栈详情,「虎躯一震」哟,高端的,这堆栈后面的还有类的包路径信息呢呢,以前看堆栈的时候咋没有特别注意
坐下打开电脑翻看了下一下Logback的代码核心计算逻辑ch.qos.logback.classic.spi.PackagingDataCalculator
获取Package
下的MANIFEST.MF
文件里面Implementation-Version
信息
和获取类所在的jar
包路径
可以看到所有的信息都在类对应的Class对象上
深入思考
很多时候为了解决Maven扁平化依赖臃肿和依赖冲突问题,我们往往会用上类隔离框架,比如说支付宝开源的sofa-ark,其基本原理就是使用单独的ClassLoader
加载,并且将一部门类EXPORT
,假设如果遇到没有被EXPORT
出来的类(幽灵Class),会发生什么情况呢?
分析
因为是属于没有被EXPORT
出来的类所以最终会委托给应用类加载器加载
为了防止重复加载,所以应用类加载器在加载类的时候会根据加载的className
加锁,因为类也不是应用类加载器加载的所以会进行双亲委派加载,最后抛出ClassNotFoundException
,再结合PackagingDataCalculator
对异常的处理程序不会终止,所以我们可以得出结论只要碰到「幽灵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...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。