OSGi常见问题总结


本文适合在部署OSGi系统【确切的是Equinox】时, 遇到问题的解决方法。 更基础理论和实践,请按照下面的链接进行索引,绝大部分案例都提供了源码。

 1OSGI学习手册

2 服务端架构技术——基于OSGI服务端的架构设计和实现

3 OSGI 进阶学习——《OSGI In Practice阅读总结

4OSGI项目持续集成(环境搭建, 编译和发布总结)

 

 

1.1运行时的ClassNotFoundException

编译时的问题都好解决, Eclipse会给足够提示

情形1: 间接引用带来的问题

原因:Plugin_1 没有直接使用Plugin_2的Java文件,但运行时使用了Plugin_2中的Jar包中的文件。

解决措施:将Plugin_2中的Jar包导出来, 同时在Plugin_1中导入这些包:


图一:导出, 使其可被访问


 

图二: 设置依赖, 使其可以访问

情形2: 利用String反射到类或对象的时候出现的问题

Plugin_1涉及到由String转化为类对象Plugin_2_ClassA(Plugin_2_ClassA表示Plugin_2中的Class  A)的操作, 这个时候调用非常隐晦, 也需要按照情形1进行处理.

情形3: 加载顺序不对带来的问题

IDE环境下, 这个问题出现在控制台中
IDE环境下, 这个问题出现在configuration目录下面的Log目录中

特别提醒: 不要手动生成一个插件, 非常容易造成该问题.

Caused by: java.lang.ClassNotFoundException: cn.com.sany.isw.service.mixingstation.service.TruckService

        at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:506)

        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)

        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)

        at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)

        at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

        ... 16 more

Root exception:

java.lang.NoClassDefFoundError: cn/com/sany/isw/service/mixingstation/service/TruckService

        at cn.com.sany.isw.service.bplpush.Activator.startAllRecievePushMsgThread(Activator.java:151)

        at cn.com.sany.isw.service.bplpush.Activator.start(Activator.java:77)

        at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:783)

        at java.security.AccessController.doPrivileged(Native Method)

1. 如果是IDE环境下出现的问题,   Run Configuration中配置一下启动顺序

2. 发布环境下, config.ini 需要做新的调整,先加载底层插件,再加载依赖插件,最后加载不被任何插件依赖的项目 (参见文章开始的参考资料4)

3. 发布环境下, 如果问题一再出现, 请删除\configuration目录下的org.eclipse.osgi 目录, 再进行启动

1.2运行时的NoClassDefFoundError

情形一: 发布环境下,某个需要的Jar包Class未定义

该问题在Eclipse环境下表现非常正常, 但发布出去后直接报错,这个都是由于Jar包包含引起的问题, 这里不做具体详述:

参考: 解决OSGI环境第三方包的NoClassDefFoundError

点评: 这个Error追踪了半天, 这里阐述了一个解决方案, 但原理性的解释, 还需要自己进一步探讨, 可以确定的是: 这个解决方案很凑效. 问题是这么解决的——1. 将第三方包作为Bundle 2. 在改bundle中的Manifest.MF文件中加入上文所说的.DynamicImport-Package

情形二: 发布环境下, 某个J2SE/Eclipse框架的Class文件未定义

加载org.w3c.dom, 发布的时候,出现classNotfoundErr问题, 解决方案: 在import package中,增加org.w3c.dom,版本号改为0.0.0 

【本问题相当NB, 重申一下特征: 系统自带的jar包出现ClassNotFound Error, 修改版本号的位置, 从上面两个图中可以看出来】

1.3运行时报资源文件找不到

Plugin_2访问Plugin_1, 但其中Plugin_1加载了一个资源文件p1.xml,这个资源文件中p1.xml中配置了一个相对路径<relative_path>.

l  按照常理, 我们把Plugin_1中的资源文件放在Eclipse安装目录下, 这个没问题,完全可以访问。

l  那么<relative_path>中应该放在哪里? 注意,需要放在解析relative_path这个文件的类所在的classpath路径。比如,Plugin_1采用了第三方包jar_1,并将这个jar_1放置在Plugin_10中,那么,这个relative_path描述的资源文件就应该放在Plugin_10中。参考《OSGi轻量级数据库解决方案》中将描述Ibatis这个数据框架中配置问题,将有更直观认识。

1.4编译环境下,无法Import某个Class

Plugin_1中无法Import Plugin_2的jar包中的类Plugin_2_JAR_CLASS_A

l  按照1.1情形一的方式检查: Plugin_2的jar是否做了runtime导出设置,Plugin_1是否做了Dependency引入

l  是否在ClassPath中做了添加Jar包的操作,见下图的ClassPath

 

图三: 设置ClassPath, 将第三方包加入

如果还是不行, 将上一步加入的Jar包删除再添加一次, 这个绝杀了大部分的问题, 另外一方面也觉得这个Bug是否太低级了一点点?】

1.5为避免死锁, 对象初始化不完全的问题

问题特征有两个错误提示:

错误提示一: To avoid deadlock, is proceeding but may not be fully initialized

!MESSAGE While loading class "cn.com.sany.isw.service.m2m.M2MDB", thread "Thread[Thread-6,5,main]" timed out waiting (5000ms) for thread "Thread[Start Level Event Dispatcher,5,main]" to finish starting bundle "cn.com.sany.isw.service.m2m_1.0.0 [21]". To avoid deadlock, thread "Thread[Thread-6,5,main]" is proceeding but "cn.com.sany.isw.service.m2m.M2MDB" may not be fully initialized.

错误提示二: Unknow resource

org.osgi.framework.BundleException: State change in progress for bundle "initial@reference:file:E:/projects/osgi/ISW_2012_6/cn.com.sany.isw.service.m2m/" by thread "Start Level Event Dispatcher".
	at org.eclipse.osgi.framework.internal.core.AbstractBundle.beginStateChange(AbstractBundle.java:1077)
	at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:282)
	at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:417)
	at org.eclipse.osgi.internal.loader.BundleLoader.setLazyTrigger(BundleLoader.java:265)
	at org.eclipse.core.runtime.internal.adaptor.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:106)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(ClasspathManager.java:453)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(DefaultClassLoader.java:216)
	at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:393)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:469)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at cn.com.sany.isw.service.m2m.shareData.ThreadHashGpsDev.run(ThreadHashGpsDev.java:65)
Caused by: org.eclipse.osgi.framework.internal.core.AbstractBundle$BundleStatusException
	... 14 more
Root exception:
org.eclipse.osgi.framework.internal.core.AbstractBundle$BundleStatusException
	at org.eclipse.osgi.framework.internal.core.AbstractBundle.beginStateChange(AbstractBundle.java:1077)
	at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:282)
	at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:417)
	at org.eclipse.osgi.internal.loader.BundleLoader.setLazyTrigger(BundleLoader.java:265)
	at org.eclipse.core.runtime.internal.adaptor.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:106)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(ClasspathManager.java:453)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(DefaultClassLoader.java:216)
	at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:393)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:469)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at cn.com.sany.isw.service.m2m.shareData.ThreadHashGpsDev.run(ThreadHashGpsDev.java:65)

该问题出现的根源是: 线程里面调用了一个需要花费大量时间初始化的类或者对象, 上述问题就是由Thread中的run方法需要调用一个类【】的静态方法, 但这个类的其他变量初始化实在是太消耗时间了, 这样非常容易导致deadlock. 于是系统为了避免deadlock, 就没有完全加载这个类从而导致问题的爆发. 这个是问题的根源, 在Thread的run方法中,有这样一个调用:

InstInfo 	info = M2MDB.getInstallInfoByDevid(devid);

我解决的方法是, 线程启动之前,就调用了一个什么都不干的类, 比如在这个Thread初始化的时候,进行一次调用M2MDB的空方法:

	public static ThreadHashGpsDev getInstance()
	{
		M2MDB.xx();
		if( null == instance)
		{
			synchronized(lockInstace)
			{
				if( null == instance)
				{
					instance = new ThreadHashGpsDev();
					initFromDB_help();
				}
			}
		}
		return instance;
	}

从而解决了整个问题。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页