grpc protobuf 中的 NoSuchMethodException 和 NoClassDefFoundError java
NoSuchMethodException and NoClassDefFoundError in grpc protobuf java
我启动了一个 gRPC 服务,一切正常,没有错误。但是,当我尝试使用 grpcui
(./grpcui -plaintext localhost:9900
) 读取服务时,我得到以下信息:
Exception in thread "grpc-default-executor-0" java.lang.NoSuchMethodError: com.google.protobuf.Descriptors$FileDescriptor.internalBuildGeneratedFileFrom([Ljava/lang/String;[Lcom/google/protobuf/Descriptors$FileDescriptor;)Lcom/google/protobuf/Descriptors$FileDescriptor;
at io.grpc.reflection.v1alpha.ServerReflectionProto.<clinit>(ServerReflectionProto.java:103)
at io.grpc.reflection.v1alpha.ServerReflectionGrpc$ServerReflectionBaseDescriptorSupplier.getFileDescriptor(ServerReflectionGrpc.java:234)
at io.grpc.protobuf.services.ProtoReflectionService$FileDescriptorIndex.<init>(ProtoReflectionService.java:418)
at io.grpc.protobuf.services.ProtoReflectionService$ServerReflectionIndex.<init>(ProtoReflectionService.java:339)
at io.grpc.protobuf.services.ProtoReflectionService.updateIndexIfNecessary(ProtoReflectionService.java:97)
at io.grpc.protobuf.services.ProtoReflectionService.serverReflectionInfo(ProtoReflectionService.java:136)
at io.grpc.reflection.v1alpha.ServerReflectionGrpc$MethodHandlers.invoke(ServerReflectionGrpc.java:220)
at io.grpc.stub.ServerCalls$StreamingServerCallHandler.startCall(ServerCalls.java:224)
at io.grpc.internal.ServerImpl$ServerTransportListenerImpl.startWrappedCall(ServerImpl.java:648)
at io.grpc.internal.ServerImpl$ServerTransportListenerImpl.startCall(ServerImpl.java:626)
at io.grpc.internal.ServerImpl$ServerTransportListenerImpl.access00(ServerImpl.java:417)
at io.grpc.internal.ServerImpl$ServerTransportListenerImplStreamCreated.runInternal(ServerImpl.java:556)
at io.grpc.internal.ServerImpl$ServerTransportListenerImplStreamCreated.runInContext(ServerImpl.java:531)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
和
Exception in thread "grpc-default-executor-1" java.lang.NoClassDefFoundError: Could not initialize class io.grpc.reflection.v1alpha.ServerReflectionProto
at io.grpc.reflection.v1alpha.ServerReflectionGrpc$ServerReflectionBaseDescriptorSupplier.getFileDescriptor(ServerReflectionGrpc.java:234)
at io.grpc.protobuf.services.ProtoReflectionService$FileDescriptorIndex.<init>(ProtoReflectionService.java:418)
at io.grpc.protobuf.services.ProtoReflectionService$ServerReflectionIndex.<init>(ProtoReflectionService.java:339)
at io.grpc.protobuf.services.ProtoReflectionService.updateIndexIfNecessary(ProtoReflectionService.java:97)
at io.grpc.protobuf.services.ProtoReflectionService.serverReflectionInfo(ProtoReflectionService.java:136)
at io.grpc.reflection.v1alpha.ServerReflectionGrpc$MethodHandlers.invoke(ServerReflectionGrpc.java:220)
at io.grpc.stub.ServerCalls$StreamingServerCallHandler.startCall(ServerCalls.java:224)
at io.grpc.internal.ServerImpl$ServerTransportListenerImpl.startWrappedCall(ServerImpl.java:648)
at io.grpc.internal.ServerImpl$ServerTransportListenerImpl.startCall(ServerImpl.java:626)
at io.grpc.internal.ServerImpl$ServerTransportListenerImpl.access00(ServerImpl.java:417)
at io.grpc.internal.ServerImpl$ServerTransportListenerImplStreamCreated.runInternal(ServerImpl.java:556)
at io.grpc.internal.ServerImpl$ServerTransportListenerImplStreamCreated.runInContext(ServerImpl.java:531)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
我的服务:
public class OneSideInitiated extends SideGrpc.SideImplBase {
@Override
public void requestStart(RemoteStartRequest request,
StreamObserver<RemoteStartResponse> responseObserver) {
RemoteStartResponse response = RemoteStartResponse.newBuilder().build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
启动服务的class:
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.protobuf.services.ProtoReflectionService;
public class StuffServer {
private Server server;
public StuffServer(int port) {
this.server = ServerBuilder.forPort(port)
.addService(ProtoReflectionService.newInstance())
.addService(new OneSideInitiated())
.build();
}
public void start() throws IOException {
server.start();
}
public void stop() throws InterruptedException {...}
public static void main(String[] args) throws Exception {
CccpServer cccpServer = new StuffServer(9900);
cccpServer.start();
cccpServer.blockUntilShutdown();
}
private void blockUntilShutdown() throws InterruptedException {...}
}
我的 Maven 依赖项是:
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.26.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-core</artifactId>
<version>1.26.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>1.26.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-services</artifactId>
<version>1.26.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.6.1-jre</version>
</dependency>
<dependency>
<groupId>com.google.api.grpc</groupId>
<artifactId>proto-google-common-protos</artifactId>
<version>0.1.9</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-testing</artifactId>
<version>1.26.0</version>
<scope>testing</scope>
</dependency>
尝试了 guava
和 io.grpc
版本的不同组合,没有任何区别。
有人对此有任何想法吗?
该特定的 FileDescriptor.internalBuildGeneratedFileFrom() 方法已在 v3.8 中添加到 Protobuf。通常 NoSuchMethodError
错误是由依赖项降级引起的,通常由 Maven 降级。
您可以运行 mvn dependency:tree
检查正在使用的依赖项版本。在这种情况下,您会发现 com.google.api.grpc:proto-google-common-protos:0.1.9
取决于 com.google.protobuf:protobuf-java:3.2.0
,这就是 Maven 使用的版本。
gRPC 团队建议始终使用 Maven Enforcer 的 requireUpperBoundDeps
来检测何时 Maven 版本选择不当。您可以添加到您的 pom.xml:
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireUpperBoundDeps/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
当它在构建过程中检测到失败时,它会提供其他地方所依赖的版本。选择最大的版本并将其作为显式依赖项添加到您的项目中:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.11.0</version>
</dependency>
我还会注意到 proto-google-common-protos:0.1.9 已经很旧了。我建议更新到更新的版本,例如 1.17.0。尽管您在 1.17.0 中仍然遇到过此问题。
我启动了一个 gRPC 服务,一切正常,没有错误。但是,当我尝试使用 grpcui
(./grpcui -plaintext localhost:9900
) 读取服务时,我得到以下信息:
Exception in thread "grpc-default-executor-0" java.lang.NoSuchMethodError: com.google.protobuf.Descriptors$FileDescriptor.internalBuildGeneratedFileFrom([Ljava/lang/String;[Lcom/google/protobuf/Descriptors$FileDescriptor;)Lcom/google/protobuf/Descriptors$FileDescriptor;
at io.grpc.reflection.v1alpha.ServerReflectionProto.<clinit>(ServerReflectionProto.java:103)
at io.grpc.reflection.v1alpha.ServerReflectionGrpc$ServerReflectionBaseDescriptorSupplier.getFileDescriptor(ServerReflectionGrpc.java:234)
at io.grpc.protobuf.services.ProtoReflectionService$FileDescriptorIndex.<init>(ProtoReflectionService.java:418)
at io.grpc.protobuf.services.ProtoReflectionService$ServerReflectionIndex.<init>(ProtoReflectionService.java:339)
at io.grpc.protobuf.services.ProtoReflectionService.updateIndexIfNecessary(ProtoReflectionService.java:97)
at io.grpc.protobuf.services.ProtoReflectionService.serverReflectionInfo(ProtoReflectionService.java:136)
at io.grpc.reflection.v1alpha.ServerReflectionGrpc$MethodHandlers.invoke(ServerReflectionGrpc.java:220)
at io.grpc.stub.ServerCalls$StreamingServerCallHandler.startCall(ServerCalls.java:224)
at io.grpc.internal.ServerImpl$ServerTransportListenerImpl.startWrappedCall(ServerImpl.java:648)
at io.grpc.internal.ServerImpl$ServerTransportListenerImpl.startCall(ServerImpl.java:626)
at io.grpc.internal.ServerImpl$ServerTransportListenerImpl.access00(ServerImpl.java:417)
at io.grpc.internal.ServerImpl$ServerTransportListenerImplStreamCreated.runInternal(ServerImpl.java:556)
at io.grpc.internal.ServerImpl$ServerTransportListenerImplStreamCreated.runInContext(ServerImpl.java:531)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
和
Exception in thread "grpc-default-executor-1" java.lang.NoClassDefFoundError: Could not initialize class io.grpc.reflection.v1alpha.ServerReflectionProto
at io.grpc.reflection.v1alpha.ServerReflectionGrpc$ServerReflectionBaseDescriptorSupplier.getFileDescriptor(ServerReflectionGrpc.java:234)
at io.grpc.protobuf.services.ProtoReflectionService$FileDescriptorIndex.<init>(ProtoReflectionService.java:418)
at io.grpc.protobuf.services.ProtoReflectionService$ServerReflectionIndex.<init>(ProtoReflectionService.java:339)
at io.grpc.protobuf.services.ProtoReflectionService.updateIndexIfNecessary(ProtoReflectionService.java:97)
at io.grpc.protobuf.services.ProtoReflectionService.serverReflectionInfo(ProtoReflectionService.java:136)
at io.grpc.reflection.v1alpha.ServerReflectionGrpc$MethodHandlers.invoke(ServerReflectionGrpc.java:220)
at io.grpc.stub.ServerCalls$StreamingServerCallHandler.startCall(ServerCalls.java:224)
at io.grpc.internal.ServerImpl$ServerTransportListenerImpl.startWrappedCall(ServerImpl.java:648)
at io.grpc.internal.ServerImpl$ServerTransportListenerImpl.startCall(ServerImpl.java:626)
at io.grpc.internal.ServerImpl$ServerTransportListenerImpl.access00(ServerImpl.java:417)
at io.grpc.internal.ServerImpl$ServerTransportListenerImplStreamCreated.runInternal(ServerImpl.java:556)
at io.grpc.internal.ServerImpl$ServerTransportListenerImplStreamCreated.runInContext(ServerImpl.java:531)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
我的服务:
public class OneSideInitiated extends SideGrpc.SideImplBase {
@Override
public void requestStart(RemoteStartRequest request,
StreamObserver<RemoteStartResponse> responseObserver) {
RemoteStartResponse response = RemoteStartResponse.newBuilder().build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
启动服务的class:
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.protobuf.services.ProtoReflectionService;
public class StuffServer {
private Server server;
public StuffServer(int port) {
this.server = ServerBuilder.forPort(port)
.addService(ProtoReflectionService.newInstance())
.addService(new OneSideInitiated())
.build();
}
public void start() throws IOException {
server.start();
}
public void stop() throws InterruptedException {...}
public static void main(String[] args) throws Exception {
CccpServer cccpServer = new StuffServer(9900);
cccpServer.start();
cccpServer.blockUntilShutdown();
}
private void blockUntilShutdown() throws InterruptedException {...}
}
我的 Maven 依赖项是:
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.26.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-core</artifactId>
<version>1.26.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>1.26.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-services</artifactId>
<version>1.26.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.6.1-jre</version>
</dependency>
<dependency>
<groupId>com.google.api.grpc</groupId>
<artifactId>proto-google-common-protos</artifactId>
<version>0.1.9</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-testing</artifactId>
<version>1.26.0</version>
<scope>testing</scope>
</dependency>
尝试了 guava
和 io.grpc
版本的不同组合,没有任何区别。
有人对此有任何想法吗?
该特定的 FileDescriptor.internalBuildGeneratedFileFrom() 方法已在 v3.8 中添加到 Protobuf。通常 NoSuchMethodError
错误是由依赖项降级引起的,通常由 Maven 降级。
您可以运行 mvn dependency:tree
检查正在使用的依赖项版本。在这种情况下,您会发现 com.google.api.grpc:proto-google-common-protos:0.1.9
取决于 com.google.protobuf:protobuf-java:3.2.0
,这就是 Maven 使用的版本。
gRPC 团队建议始终使用 Maven Enforcer 的 requireUpperBoundDeps
来检测何时 Maven 版本选择不当。您可以添加到您的 pom.xml:
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireUpperBoundDeps/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
当它在构建过程中检测到失败时,它会提供其他地方所依赖的版本。选择最大的版本并将其作为显式依赖项添加到您的项目中:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.11.0</version>
</dependency>
我还会注意到 proto-google-common-protos:0.1.9 已经很旧了。我建议更新到更新的版本,例如 1.17.0。尽管您在 1.17.0 中仍然遇到过此问题。