偶然一次路过同事电脑,看着黑底蓝色满屏的堆栈信息,过去笑着拍了拍他的肩膀说道「小哥,又在写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...