请教一下java.lang.LinkageError的根本原因是什么?

问题描述:
我在尝试将springboot应用集成到另一个容器中时候,计划是将springboot应用的日志统一到另一个容器中进行管理,所以,特别处理了下springboot org.springframework.boot.loader.LaunchedURLClassLoader 的委托加载关系,将若干日志package委托 parent加载:
比如:

org.slf4j.impl
org.slf4j.bridge
ch.qos.logback.core.joran.spi
...
ch.qos.logback.classic
ch.qos.logback.classic.joran
...

由于遗漏了 ch.qos.logback.classic.spi.TurboFilterList 所在包ch.qos.logback.classic.spi的委托关系,所以,运行时报错如下:

Caused by: java.lang.LinkageError: loader constraint violation: loader (instance of org/springframework/boot/loader/LaunchedURLClassLoader) 
previously initiated loading for a different type with name "ch/qos/logback/classic/spi/TurboFilterList"

报错的源码位置:

我现在的疑问是:
对Springboot的LaunchedURLClassLoader来说,
ch.qos.logback.classic.spi.TurboFilterList类应该是由 LaunchedURLClassLoader来定义的,然而:loggerContext.getTurboFilterList() 返回的对象类“TurboFilterList” 是由parent classloader 来定义的, 所以,报错不应该是:ClassCastException 吗?
为什么却是在 ClassLoader.defineClass 时抛出了一个LinkageError?

阅读 1.9k
avatarAI BotBETA

java.lang.LinkageError的根本原因是因为在定义类时使用了不同的类加载器,导致类之间的依赖关系出现问题。在你的情况下,ch.qos.logback.classic.spi.TurboFilterList类是由父类加载器定义的,而LaunchedURLClassLoader在定义自己的类时使用了不同的类加载器,导致两者之间的依赖关系出现问题。

具体来说,当你使用LaunchedURLClassLoader加载ch.qos.logback.classic.spi.TurboFilterList类时,它尝试定义一个名为"ch/qos/logback/classic/spi/TurboFilterList"的类。但是,在这个时候,一个加载器正在使用这个名字来定义另一个不同的类。这导致两个类之间出现了命名冲突,导致了LinkageError。

具体来说,当你使用LaunchedURLClassLoader加载ch.qos.logback.classic.spi.TurboFilterList类时,它尝试定义一个名为"ch/qos/logback/classic/spi/TurboFilterList"的类。但是,在这个时候,一个加载器正在使用这个名字来定义另一个不同的类。这导致两个类之间出现了命名冲突,导致了LinkageError。

对于你的问题,我建议你在处理LaunchedURLClassLoader的委托加载关系时,确保所有依赖关系都正确设置,并且不会出现命名冲突。这可能需要你重新审视你的代码逻辑,确保所有依赖关系都被正确处理,并且没有出现命名冲突的情况。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题