【问题标题】:NoClassDefFoundError for a class due to the interrelative dependencies in karaf由于 karaf 中的相互依赖关系,类的 NoClassDefFoundError
【发布时间】:2021-07-28 17:51:42
【问题描述】:

考虑以下我遇到意外错误且无法修复的情况。

在 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: io.example.Test 无法被 org.opendaylight 找到

我发现 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)..

【问题讨论】:

    标签: grpc classnotfoundexception noclassdeffounderror apache-karaf opendaylight


    【解决方案1】:

    在 OSGi 和 Karaf 中出现ClassNotFoundException 的一个常见原因是多个包导出具有相同版本的相同包。这会导致只导入其中一个,它可能包含也可能不包含您的 Test 类。

    使用 package:exports 命令检查哪些包导出 io.example:

    packages:exports -p io.example
    

    我猜测添加依赖项会导致您的包从io-example-api 导入包io.example 而不是io-example

    解决方案是确保只有一个包导出 io.example 包。

    [编辑] 我对 grpc 不熟悉,但似乎有 issue on github 关于这个和一些你可以查看的解决方法。

    您也可以尝试创建一个嵌入这些有问题的依赖项的包并导出这些包以供其他包使用。

    1. 使用原型karaf-bundle-archetype 创建一个新的捆绑项目
    2. 添加 grpc-contextgrpc-api 依赖项
    3. 配置 maven-bundle-plugin 以嵌入 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());
    

    【讨论】:

    • 感谢您的帮助.. 你说得对.. 两个包导出的包相同。
    • 我已经更新了问题中的详细信息。请查看并提供任何建议。 @Pasi Österman
    • 发现与此相关的 Github 问题并测试了一种方法,可以创建一个捆绑包以将这些有问题的依赖项保存为 Emped 依赖项,并导出这些包以供其他捆绑包在 karaf 中使用。但是由于我对 grpc 不熟悉,因此只对其进行了一些简单的测试,因此您可能仍然会遇到一些问题,但希望它可以帮助您前进。更新了答案。
    猜你喜欢
    • 2011-06-26
    • 1970-01-01
    • 2022-08-14
    • 2013-08-04
    • 2021-10-17
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多