IntelliJ IDEA插件开发中Ktor Client使用异常求助
在IntelliJ IDEA插件中使用Ktor Client WebSocket遇到的类加载冲突问题
问题场景
我正在开发IntelliJ IDEA插件,想要使用Ktor Client的WebSocket功能,核心代码如下:
val client = HttpClient(CIO) { install(WebSockets) }
调用client.webSocket(...)时抛出以下异常:
java.lang.LinkageError: loader constraint violation: when resolving method 'org.slf4j.ILoggerFactory org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()' the class loader com.intellij.ide.plugins.cl.PluginClassLoader @a02df19 of the current class, org/slf4j/LoggerFactory, and the class loader com.intellij.util.lang.PathClassLoader @2ac1fdc4 for the method's defining class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type org/slf4j/ILoggerFactory used in the signature (org.slf4j.LoggerFactory is in unnamed module of loader com.intellij.ide.plugins.cl.PluginClassLoader @a02df19, parent loader 'bootstrap'; org.slf4j.impl.StaticLoggerBinder is in unnamed module of loader com.intellij.util.lang.PathClassLoader @2ac1fdc4) at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:423) ... java.lang.NoClassDefFoundError: Could not initialize class io.ktor.client.plugins.websocket.WebSocketsKt ...
测试Ktor Server时也出现相同异常。后续发现添加Ktor依赖后,即使不使用Ktor,调用org.slf4j.LoggerFactory.getILoggerFactory()也会抛出异常。
疑问
- 在IDEA插件中使用Ktor是否可行?
- 若可行,该如何修复此问题?
使用版本
kotlinVersion = "1.8.0" ideaPluginVersion = "1.13.1" ktorVersion = "2.2.2"
完整build.gradle.kts配置
plugins { id("java") id("org.jetbrains.kotlin.jvm") version "1.8.0" id("org.jetbrains.intellij") version "1.13.1" } group = "com.example" version = "1.0-SNAPSHOT" repositories { mavenCentral() } intellij { version.set("2022.1.4") type.set("IC") plugins.set(listOf(/* Plugin Dependencies */)) } dependencies { val ktorVersion = "2.2.2" implementation("io.ktor:ktor-client-core:$ktorVersion") implementation("io.ktor:ktor-client-cio:$ktorVersion") implementation("io.ktor:ktor-client-websockets:$ktorVersion") } tasks { withType<JavaCompile> { sourceCompatibility = "11" targetCompatibility = "11" } withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> { kotlinOptions.jvmTarget = "11" } patchPluginXml { sinceBuild.set("221") untilBuild.set("231.*") } signPlugin { certificateChain.set(System.getenv("CERTIFICATE_CHAIN")) privateKey.set(System.getenv("PRIVATE_KEY")) password.set(System.getenv("PRIVATE_KEY_PASSWORD")) } publishPlugin { token.set(System.getenv("PUBLISH_TOKEN")) } }
临时解决方案
我临时通过在build.gradle.kts中添加以下配置解决了问题,但不确定是否合理:
configurations.all { exclude("org.slf4j", "slf4j-api") }
解答
1. 在IDEA插件中使用Ktor是否可行?
完全可行,不少IDEA插件都在使用Ktor进行网络通信(包括WebSocket),只要处理好类加载和依赖冲突问题即可。
2. 如何修复此问题?
你遇到的是SLF4J类加载冲突:IntelliJ IDEA本身已经自带了SLF4J的API和实现,而Ktor依赖也引入了SLF4J API,导致插件类加载器和IDE的类加载器加载了不同版本的SLF4J相关类,引发约束冲突。
你的临时解决方案是合理的,但可以更精准,避免全局排除:
- 只排除Ktor依赖中的SLF4J API,而不是所有配置中的:
dependencies { val ktorVersion = "2.2.2" implementation("io.ktor:ktor-client-core:$ktorVersion") { exclude(group = "org.slf4j", module = "slf4j-api") } implementation("io.ktor:ktor-client-cio:$ktorVersion") { exclude(group = "org.slf4j", module = "slf4j-api") } implementation("io.ktor:ktor-client-websockets:$ktorVersion") { exclude(group = "org.slf4j", module = "slf4j-api") } }
这样做的原因是:IDEA已经提供了SLF4J的API和实现,插件直接使用IDE提供的即可,不需要自己打包SLF4J API。
另外,也可以通过intellij插件的配置来确保依赖使用IDE提供的版本:
intellij { // ... 其他原有配置 configureDependencies { compileOnly("org.slf4j:slf4j-api") } }
不过更推荐第一种精准排除的方式,因为它直接避免了重复依赖的引入。
内容的提问来源于stack exchange,提问作者AmirHossein Abdolmotallebi
相关产品推荐
相关产品推荐

