obr安装资源的时抛出异常:java.lang.IllegalStateException: Framework state has changed, must resolve again.

Apache Felix OSGi Bundle Repository

Apache Felix OSGi Bundle Repository

在使用obrApache Felix OSGi Bundle Repository)的实现类org.apache.felix.bundlerepository.Resolver分析和安装资源的时可能会抛出这个异常:java.lang.IllegalStateException: Framework state has changed, must resolve again.

见代码:

在deploy之前先调用resolve方法,确保这个resolver所需的requirement都能满足,如果有任意的requirement没有满足,都进不了if语句里面。但是有时会碰到resolver.resolve()返回true时,执行deploy抛出上面的异常的情况。

异常堆栈如下:

java.lang.IllegalStateException: Framework state has changed, must resolve again.

at org.apache.felix.bundlerepository.impl.ResolverImpl.deploy(ResolverImpl.java:500)

。。。。。

原因在ResolverImpl.java的deploy(int)方法中,见如下的代码:

m_repositories[repoIdx].getLastModified()这是每个repository的最后一次的修改时间

m_resolveTimeStamp这是所有repository在执行resolve()方式时初始化的一个时间,这个时间是所有的repository最后修改时间的最大值。

上面的判断是为了确保在执行resolve()方法和deploy(int)方法之间,所有的repository都没有被修改。

而某些特殊情况由于异步执行的原因可能导致某些repository的最后修改时间在执行resolve()后deploy(int)之前被修改。下面是具体的分析:

m_repositories可以分为三种:LocalRepositoryImpl、RepositoryImpl、SystemRepositoryImpl。其中LocalRepositoryImpl实现了SynchronousBundleListener接口和AllServiceListener接口的serviceChanged(ServiceEvent event)方法,由于SynchronousBundleListener是会在bundle安装和卸载时同步调用的,所以只要不异步的安装bundle(通常安装bundle都是通过resolver.deploy(int)方法来安装)就不会出现LocalRepositoryImpl被异步修改的情况的情况; 但是AllServiceListener接口的serviceChanged(ServiceEvent event)方法会在service注册和删除时修改LocalRepositoryImpl的repository最后修改时间,而bundle中的service的安装就不一定是同步的了,比如Felix iPOJO的instance的创建和注册默认情况就是异步进行的,很有可能出现service的注册发生在resolve()后,deploy(int)之前。见LocalRepositoryImpl.java中的代码:

可见如果安装了一个bundle,里面有了ipojo的instance,那么这些instance会被异步的注册到osgi中,上面的方法会被异步的调用,就会导致resolve()后,LocalRepositoryImpl的时间戳被修改,再执行deploy(int)时出现标题中的异常了。

解决办法一:如异常中所说,就是把这个resolver重新resolve一次,如下面的代码:

解决办法二:把ipojo的instance注册方式设置为同步的。ipojo提供了多个渠道可以设置instance同步注册,相关源码详见:org.apache.felix.ipojo.extender.internal.Extender.enablingSynchronousProcessing()方法
方法1:在felix的Framework properties中添加一个参数ipojo.processing.synchronous=true
方法2:在系统参数中添加ipojo.processing.synchronous=true
方法3:在org.apache.felix.ipojo bundle的menifest.mf文件中添加head信息:ipojo-processing-synchronous=true

Post Footer automatically generated by wp-posturl plugin for wordpress.



  1. 看的不是太明白。
    SynchronousBundleListener 和 ipojo.processing.synchronous=true 之间好像并没有太大的关系?

    不过仍然多谢博主分享