运行gRPC Kotlin客户端时遭遇java.lang.NoClassDefFoundError错误
问题:Spring Boot gRPC Kotlin客户端启动时出现NoClassDefFoundError错误
执行main函数时抛出如下错误:
java.lang.NoClassDefFoundError: io/grpc/ClientStreamTracer$InternalLimitedInfoFactory at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1023) at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862) at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) at io.grpc.internal.ManagedChannelImpl$ChannelStreamProvider.newStream(ManagedChannelImpl.java:591) at io.grpc.internal.ClientCallImpl.startInternal(ClientCallImpl.java:256) at io.grpc.internal.ClientCallImpl.start(ClientCallImpl.java:189) at io.grpc.internal.DelayedClientCall$1.run(DelayedClientCall.java:180) at io.grpc.internal.DelayedClientCall.drainPendingCalls(DelayedClientCall.java:278) at io.grpc.internal.DelayedClientCall.setCall(DelayedClientCall.java:152) at io.grpc.internal.ManagedChannelImpl$RealChannel$PendingCall$1.run(ManagedChannelImpl.java:1107) at io.grpc.stub.ClientCalls$ThreadlessExecutor.runQuietly(ClientCalls.java:777) at io.grpc.stub.ClientCalls$ThreadlessExecutor.waitAndDrain(ClientCalls.java:760) at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:161) at com.example.grpc.HelloWorldServiceGrpc$HelloWorldServiceBlockingStub.sayHello(HelloWorldServiceGrpc.java:157) at com.example.howbeapiserver.HelloClient.sayHelloWithBlocking(HelloClient.kt:26) at com.example.howbeapiserver.HowbeApiserverApplicationKt.main(HowbeApiserverApplication.kt:11) Caused by: java.lang.ClassNotFoundException: io.grpc.ClientStreamTracer$InternalLimitedInfoFactory at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) ... 22 more
项目相关配置
build.gradle.kts
import com.google.protobuf.gradle.* plugins { id("org.springframework.boot") version "3.3.2" id("io.spring.dependency-management") version "1.1.6" kotlin("jvm") version "1.9.24" kotlin("plugin.spring") version "1.9.24" id("com.google.protobuf") version "0.9.4" } java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } repositories { mavenCentral() } val grpcKotlinVersion by extra("1.4.1") val grpcVersion by extra("1.65.1") val grpcProtobufVersion by extra("4.27.2") dependencies { implementation("org.springframework.boot:spring-boot-starter-web") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.jetbrains.kotlin:kotlin-reflect") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") testRuntimeOnly("org.junit.platform:junit-platform-launcher") implementation("io.grpc:grpc-kotlin-stub:$grpcKotlinVersion") implementation("io.grpc:grpc-stub:$grpcVersion") implementation("io.grpc:grpc-protobuf:$grpcVersion") implementation("io.grpc:grpc-netty-shaded:$grpcVersion") implementation("com.google.protobuf:protobuf-kotlin:$grpcProtobufVersion") } sourceSets { getByName("main") { java { srcDirs( "build/generated/source/proto/main/java", "build/generated/source/proto/main/kotlin" ) } } } protobuf { protoc { artifact = "com.google.protobuf:protoc:$grpcProtobufVersion" } plugins { create("grpc") { artifact = "io.grpc:protoc-gen-grpc-java:$grpcVersion" } create("grpckt") { artifact = "io.grpc:protoc-gen-grpc-kotlin:$grpcKotlinVersion:jdk8@jar" } } generateProtoTasks { all().forEach { it.plugins { create("grpc") create("grpckt") } it.builtins { create("kotlin") } } } }
HelloClient.kt
package com.example.howbeapiserver import com.example.grpc.HelloRequest import com.example.grpc.HelloReply import com.example.grpc.HelloWorldServiceGrpc import io.grpc.ManagedChannel import io.grpc.ManagedChannelBuilder class HelloClient(host: String?, port: Int) { private var managedChannel: ManagedChannel? = null private var blockingStub: HelloWorldServiceGrpc.HelloWorldServiceBlockingStub? = null private var asyncStub: HelloWorldServiceGrpc.HelloWorldServiceStub? = null init { managedChannel = ManagedChannelBuilder .forAddress(host, port) .usePlaintext() .build() blockingStub = HelloWorldServiceGrpc.newBlockingStub(managedChannel) asyncStub = HelloWorldServiceGrpc.newStub(managedChannel) } fun sayHelloWithBlocking(message: String): HelloReply { val request = buildRequest(message) return blockingStub!!.sayHello(request) } private fun buildRequest(message: String): HelloRequest { return HelloRequest.newBuilder() .setName(message) .build() } }
HowbeApiserverApplication.kt
package com.example.howbeapiserver import org.springframework.boot.autoconfigure.SpringBootApplication @SpringBootApplication class HowbeApiserverApplication fun main(args: Array<String>) { //runApplication<HowbeApiserverApplication>(*args) val helloClient = HelloClient("localhost", 50051) println(helloClient.sayHelloWithBlocking("hello world").message) }
配置已按文档添加,但仍出现类加载错误,需排查原因并给出解决方案。
解决方案
问题原因
io.grpc.ClientStreamTracer$InternalLimitedInfoFactory 属于gRPC核心库内部API,出现找不到的情况核心原因是依赖版本不兼容:
- Spring Boot 3.3.2的依赖管理可能引入了与指定
grpcVersion=1.65.1不匹配的gRPC依赖,导致类路径中存在多版本gRPC核心库,引发类缺失。 grpc-kotlin-stub:1.4.1与grpcVersion=1.65.1存在版本适配冲突,两者核心依赖版本不一致。
解决步骤
1. 统一gRPC及Kotlin gRPC版本
根据gRPC Kotlin官方版本适配规则,将grpcVersion调整为与grpcKotlinVersion=1.4.1兼容的版本(如1.64.0),修改build.gradle.kts中的版本变量:
val grpcKotlinVersion by extra("1.4.1") val grpcVersion by extra("1.64.0") // 与grpc-kotlin-stub:1.4.1匹配的版本 val grpcProtobufVersion by extra("4.27.2")
2. 锁定gRPC依赖版本,避免Spring Boot覆盖
在build.gradle.kts中添加dependencyManagement块,强制所有gRPC相关依赖使用指定版本:
dependencyManagement { imports { mavenBom("io.grpc:grpc-bom:${grpcVersion}") } }
3. 清理并重新构建项目
执行命令清理缓存、重新生成proto代码并构建:
./gradlew clean build
4. 验证依赖版本一致性
通过./gradlew dependencies命令查看gRPC相关依赖的版本,确保所有gRPC核心、stub、netty等依赖均为指定的grpcVersion,无版本冲突。
5. (可选)使用Spring Boot gRPC Starter简化配置
若允许,引入Spring Boot gRPC Starter自动处理版本兼容:
implementation("net.devh:grpc-spring-boot-starter:2.15.0.RELEASE")
注意该Starter版本需与Spring Boot 3.3.x匹配,推荐使用2.15.x系列。
内容的提问来源于stack exchange,提问作者정하우
相关产品推荐
相关产品推荐

