OSGI bundle 运行报错 java.lang.ClassNotFoundException & java.lang.NoClassDefFoundError

OSGI bundle 运行报错 java.lang.ClassNotFoundException & java.lang.NoClassDefFoundError

在 helloworld-server bundle 中引入了 MySQL JDBC 驱动包(mysql-connector-java-5.1.35-bin.jar),helloworld-client bundle 调用 helloworld-server bundle MySQL 连接测试接口时报错,驱动加载失败。

OSGI bundle 运行报错 java.lang.ClassNotFoundException & java.lang.NoClassDefFoundError_第1张图片

OSGI bundle 运行报错 java.lang.ClassNotFoundException & java.lang.NoClassDefFoundError_第2张图片


测试过程中,里遇下面两种类型的报错:

错误1:ClassNotFoundException
...
!MESSAGE FrameworkEvent ERROR
!STACK 0
org.osgi.framework.BundleException: Exception in com.xxx.osgi.helloworld.client.Activator.start() of bundle helloworld_client.
    at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:839)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:767)
    at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:1032)
    at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:371)
    at org.eclipse.osgi.container.Module.doStart(Module.java:605)
    at org.eclipse.osgi.container.Module.start(Module.java:468)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1852)
    at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1845)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1788)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1750)
    at org.eclipse.osgi.container.SystemModule.startWorker(SystemModule.java:269)
    at org.eclipse.osgi.container.Module.doStart(Module.java:605)
    at org.eclipse.osgi.container.Module.start(Module.java:468)
    at org.eclipse.osgi.container.SystemModule.start(SystemModule.java:193)
    at org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:445)
    at org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:464)
    at org.eclipse.osgi.launch.Equinox.start(Equinox.java:139)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.startup(EclipseStarter.java:338)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:251)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.main(EclipseStarter.java:228)
Caused by: java.lang.NoClassDefFoundError: javax/crypto/NoSuchPaddingException
    at com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:334)
    at com.mysql.cj.protocol.a.NativeAuthenticationProvider.negotiateSSLConnection(NativeAuthenticationProvider.java:777)
    at com.mysql.cj.protocol.a.NativeAuthenticationProvider.proceedHandshakeWithPluggableAuthentication(NativeAuthenticationProvider.java:486)
    at com.mysql.cj.protocol.a.NativeAuthenticationProvider.connect(NativeAuthenticationProvider.java:202)
    at com.mysql.cj.protocol.a.NativeProtocol.connect(NativeProtocol.java:1449)
    at com.mysql.cj.NativeSession.connect(NativeSession.java:165)
    at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:955)
    at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:825)
    at com.mysql.cj.jdbc.ConnectionImpl.(ConnectionImpl.java:455)
    at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240)
    at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199)
    at java.sql.DriverManager.getConnection(DriverManager.java:664)
    at java.sql.DriverManager.getConnection(DriverManager.java:247)
    

错误2:NoClassDefFoundError
...
!MESSAGE FrameworkEvent ERROR
!STACK 0
org.osgi.framework.BundleException: Exception in com.xxx.osgi.helloworld.client.Activator.start() of bundle helloworld_client.
    at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:839)
    at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:767)
    at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:1032)
    at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:371)
    at org.eclipse.osgi.container.Module.doStart(Module.java:605)
    at org.eclipse.osgi.container.Module.start(Module.java:468)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1852)
    at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1845)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1788)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1750)
    at org.eclipse.osgi.container.SystemModule.startWorker(SystemModule.java:269)
    at org.eclipse.osgi.container.Module.doStart(Module.java:605)
    at org.eclipse.osgi.container.Module.start(Module.java:468)
    at org.eclipse.osgi.container.SystemModule.start(SystemModule.java:193)
    at org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:445)
    at org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:464)
    at org.eclipse.osgi.launch.Equinox.start(Equinox.java:139)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.startup(EclipseStarter.java:338)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:251)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.main(EclipseStarter.java:228)
Caused by: java.lang.NoClassDefFoundError: javax/naming/NamingException
    at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:186)
    at java.sql.DriverManager.getConnection(DriverManager.java:664)
    at java.sql.DriverManager.getConnection(DriverManager.java:247)
    at com.xxx.osgi.helloworld.server.MySQLConnImpl.selectTest(MySQLConnImpl.java:78)
    at com.xxx.osgi.helloworld.client.Activator.mysqlConnectorServiceTest(Activator.java:59)

g! install my_bundles/mysql-connector-java-5.1.35-bin.jar
Bundle ID: 45
g! install my_bundles/helloworld-server-1.0.0-SNAPSHOT.jar
Bundle ID: 46
g! install my_bundles/helloworld-client-1.0.0-SNAPSHOT.jar
Bundle ID: 47
g! ss
"Framework is launched."


id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.18.600.v20231110-1900
1       ACTIVE      org.eclipse.equinox.console_1.4.600.v20231106-0859
2       INSTALLED   org.eclipse.core.jobs_3.15.100.v20230930-1207
3       INSTALLED   org.eclipse.core.runtime_3.30.0.v20231102-0719
4       INSTALLED   org.eclipse.equinox.common_3.18.200.v20231106-1826
5       ACTIVE      org.apache.felix.gogo.command_1.1.2
6       ACTIVE      org.apache.felix.gogo.runtime_1.1.6
7       ACTIVE      org.apache.felix.gogo.shell_1.1.4
45      INSTALLED   com.mysql.jdbc_5.1.35
46      INSTALLED   helloworld_server_1.0.0.SNAPSHOT
47      INSTALLED   helloworld_client_1.0.0.SNAPSHOT
g! start 45

g! start 46
helloworld-server: start
helloworld-server: helloworld 服务已发布(注册)!
helloworld-server: mysqlConn 服务已发布(注册)!

g! start 47
helloworld-client: start
helloworld-client: call server getHelloMsg()
SUCCESS: return msg is:
[getHelloMsg:29]  HelloWorld Frank
[selectTest:65] ERROR: jdbc driver load failed, ClassNotFound!
java.sql.SQLException: java.lang.NoClassDefFoundError: javax/naming/RefAddr
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:998)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:937)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:872)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:904)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:894)
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:407)
        at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:399)
        at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:325)
        at java.sql.DriverManager.getConnection(DriverManager.java:664)
        at java.sql.DriverManager.getConnection(DriverManager.java:247)
        at com.xxx.osgi.helloworld.server.MySQLConnImpl.selectTest(MySQLConnImpl.java:46)
        at com.xxx.osgi.helloworld.client.Activator.mysqlConnectorServiceTest(Activator.java:59)
        at com.xxx.osgi.helloworld.client.Activator.start(Activator.java:35)
        at org.eclipse.osgi.internal.framework.BundleContextImpl$2.run(BundleContextImpl.java:818)
        at org.eclipse.osgi.internal.framework.BundleContextImpl$2.run(BundleContextImpl.java:1)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:810)
        at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:767)
        at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:1032)
        at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:371)
        at org.eclipse.osgi.container.Module.doStart(Module.java:605)
        at org.eclipse.osgi.container.Module.start(Module.java:468)
        at org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:445)
        at org.apache.felix.gogo.command.Basic.start(Basic.java:692)
        at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.apache.felix.gogo.runtime.Reflective.invoke(Reflective.java:143)
        at org.apache.felix.gogo.runtime.CommandProxy.execute(CommandProxy.java:91)
        at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:599)
        at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:526)
        at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:415)
        at org.apache.felix.gogo.runtime.Pipe.doCall(Pipe.java:416)
        at org.apache.felix.gogo.runtime.Pipe.call(Pipe.java:229)
        at org.apache.felix.gogo.runtime.Pipe.call(Pipe.java:59)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoClassDefFoundError: javax/naming/RefAddr
        at com.mysql.jdbc.ConnectionPropertiesImpl.(ConnectionPropertiesImpl.java:657)
        at com.mysql.jdbc.ConnectionImpl.(ConnectionImpl.java:696)
        at com.mysql.jdbc.JDBC4Connection.(JDBC4Connection.java:44)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:389)
        ... 33 more
Caused by: java.lang.ClassNotFoundException: javax.naming.RefAddr cannot be found by helloworld_server_1.0.0.SNAPSHOT
        at org.eclipse.osgi.internal.loader.BundleLoader.generateException(BundleLoader.java:541)
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass0(BundleLoader.java:536)
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:416)
        at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:168)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 41 more
SUCCESS: mysqlConnectorServiceTest(), result:


最终的解决办法:
修改 pom ,增加 Dynamicimport-Package 配置:com.mysql.*
或者配置成 *
我之前是在配置 中导出 com.mysql.*。改为后:

OSGI bundle 运行报错 java.lang.ClassNotFoundException & java.lang.NoClassDefFoundError_第3张图片

执行结果:

g! stop 45 46 47
g! uninstall 45 46 47
g! 
g! install my_bundles/mysql-connector-java-5.1.35-bin.jar
g! Bundle ID: 48
g! install my_bundles/helloworld-server-1.0.0-SNAPSHOT.jar
g! Bundle ID: 49
g! install my_bundles/helloworld-client-1.0.0-SNAPSHOT.jar
g! Bundle ID: 50
g! 
g! start 48
g! start 49
helloworld-server: start
helloworld-server: helloworld 服务已发布(注册)!
helloworld-server: mysqlConn 服务已发布(注册)!

g! start 50
helloworld-client: start
helloworld-client: call server getHelloMsg()
SUCCESS: return msg is:
[getHelloMsg:29]  HelloWorld Frank
[selectTest:51] ==== Table: test01 ====
1,aaa,11
2,bbb,22
3,uu,12
4,xx,12

MySQL 连接测试成功。

1)mysql jdbc 驱动 bundle 需要先 install & start,否则会报错;
2)server bundle manifest 需要配置 Dynamicimport-Package,只 mysql jdbc bundle start,不设置 Dynamicimport-Package,也还是会报错;

网上有关于NoClassDefFoundError报错的类似介绍,项目引用了第三方包的class加载其他的类,而这些类又不在当前的 bundle 中就可能会出现这个 NoClassDefFoundError 异常
ExceptioninthreadThread-1java.lang.NoClassDefFoundError:javax/naming/NamingException
也有说配置成 DynamicImport-Package: * 。如果引入的第三方包的class加载其他的类比较多的话,可以直接配置成 * 动态导入所有依赖。
 

====== ====== ====== ====== ====== ======

mysql jdbc 驱动 jar 包也是一个bundle,从其 manifest 文件可以看出来。

为了避免手动 install & start mysql jdbc jar包,把第三方的 mysql-jdbc驱动jar包作为普通的jar包依赖打包到 helloworld-server jar包中(保存到 /lib 目录下、并自动加入 Bundle-ClassPath),

最终pom文件如下:


    
        helloworld
        com.xxx.osgi
        1.0.0-SNAPSHOT
    
    4.0.0

    helloworld-server
    bundle

    helloworld-server
    http://maven.apache.org

    
        UTF-8
    

    

        






        
            mysql
            mysql-connector-java
            5.1.35
        









    

    
        
            
                
                
                org.apache.felix
                maven-bundle-plugin
                ${parent.maven.bundle.plugin.version}
                true

                
                    
                        
                        *;scope=compile|runtime
                        /lib
                        ${project.name}
                        $(replace;${project.artifactId};-;_)
                        ${project.version}
                        com.xxx.osgi.helloworld.server.Activator
                        *
                        
                        org.osgi.framework
                        
                            com.xxx.osgi.helloworld.server;version="${project.version}"
                        
                    
                










                












            
        
    

最终生成的jar包架构和内容如下:

OSGI bundle 运行报错 java.lang.ClassNotFoundException & java.lang.NoClassDefFoundError_第4张图片

执行hellworld-server时自动会加载jdbc驱动包,不需要提前 install & start jdbc bundle: 

OSGI bundle 运行报错 java.lang.ClassNotFoundException & java.lang.NoClassDefFoundError_第5张图片

注意:如果需要把本地lib/目录下的下的第三方的jar包( dependency scope 为 system)也打入到目标jar包中去,Embed-Dependency 是做不到的,需要采用 Include-Resource 方式:

OSGI bundle 运行报错 java.lang.ClassNotFoundException & java.lang.NoClassDefFoundError_第6张图片

你可能感兴趣的:(开发,常见问题,java,开发语言)