You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行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,提问作者정하우

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 11:05:55