问题描述
考虑以下场景,其中我遇到了意外错误并且无法修复它。
在 Opendaylight 原型项目中,当我在 pom.xml 中只声明一个依赖项(即 io-example)时,我只使用了一个类(比如来自 io-example 依赖项的 test.class),没有错误。
但是如果我在 pom.xml 中再添加一个依赖项 (io-example-api),我会得到 java.lang.NoClassDefFoundError: io/example/test.class 在 org.opendaylight.gnmi.impl.base.OpenconfigInter ………………………………………………………………………………………………………………………………………………………… ………………………………………………………………………………………………………………………………………………………… 引起:java.lang.classNotFoundException:org.opendaylight 找不到 io.example.Test
我发现io.example-api有io-example作为依赖..总结一下问题,如果我在pom.xml中只有io-example,没有问题。如果我在 pom.xml 中有 io-example 和 io-example-api,我会收到 NoclassDef 错误。
即使我在依赖项部分尝试了排除选项,也没有任何效果。
提前致谢...
已编辑:
类名:io.grpc.Context
依赖:
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-context</artifactId>
<version>1.38.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-api</artifactId>
<version>1.38.0</version>
</dependency>
在 karaf 容器中,我运行了“package:exports”命令,结果是,
opendaylight-user@root>package:exports -p io.grpc
io.grpc 0.0.0 354 wrap_file__home_verizon_gnmi_gnmi_karaf_target_assembly_system_io_grpc_grpc-api_1.38.0_grpc-api-1.38.0.jar
io.grpc 0.0.0 355 wrap_file__home_verizon_gnmi_gnmi_karaf_target_assembly_system_io_grpc_grpc-context_1.38.0_grpc-context-1.38.0.ja
opendaylight-user@root>package:exports -d
io.grpc 0.0.0 354 355
You can see that,io.grpc package exported by two bundles (354 and
355)..
解决方法
OSGi 和 Karaf 中 ClassNotFoundException
的一个常见原因是多个包导出具有相同版本的相同包。这会导致仅导入其中一个,其中可能包含也可能不包含您的 Test 类。
使用 package:exports 命令检查哪些包导出 io.example:
packages:exports -p io.example
我猜测添加依赖项会导致您的包从 io.example
而不是 io-example-api
导入包 io-example
。
对此的解决方案是确保只有一个包导出 io.example
包。
[编辑] 我不熟悉 grpc,但似乎有 issue on github 和一些您可以查看的解决方法。
您还可以尝试创建一个包,嵌入这些有问题的依赖项并导出包以供其他包使用。
- 使用原型
karaf-bundle-archetype
创建一个新的捆绑项目 - 添加
grpc-context
和grpc-api
依赖项 - 配置 maven-bundle-plugin 以 emped grpc 依赖项并导出 io.grpc 包及其子包。
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${maven-bundle-plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>
${project.groupId}.${project.artifactId}
</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Bundle-Activator>com.example.Activator</Bundle-Activator>
<Import-Package>
*;resolution:=optional
</Import-Package>
<Export-Package>
io.grpc*;-split-package:=merge-first
</Export-Package>
<Emped-Dependency>
grpc-context;scope=compile|runtime;inline=true,grpc-api;scope=compile|runtime;inline=true
</Emped-Dependency>
</instructions>
</configuration>
</plugin>
成功地将包安装到 Karaf 4.2.11 并在包和另一个包中“使用”导出的 io.grpc.Context
类。
简单地从两个捆绑包的激活器中调用这个
Context grpcContext = Context.current();
System.out.println(grpcContext.getClass().getName());