聊聊幽灵Class

原由

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

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

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

clipboard.png
和获取类所在的jar包路径
能够看到全部的信息都在类对应的Class对象上并发

深刻思考

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

分析

由于是属于没有被EXPORT出来的类因此最终会委托给应用类加载器加载框架

clipboard.png

clipboard.png
为了防止重复加载,因此应用类加载器在加载类的时候会根据加载的className加锁,由于类也不是应用类加载器加载的因此会进行双亲委派加载,最后抛出ClassNotFoundException,再结合PackagingDataCalculator对异常的处理
clipboard.png程序不会终止,因此咱们能够得出结论只要碰到「幽灵Class」logback都会从新把类按照双亲委派的方式加载一遍。
有锁的地方就会有锁竞争,而且Class.load也是一个耗时的过程,因此同一个ClassName若是并发出如今日志堆栈中势必会致使一部分线程会block,这对于线上系统中简直就是灾难.spa

改进

在最近的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...日志

相关文章
相关标签/搜索