使用SpringDM导入osgi服务时发生死锁

使用SpringDM导入osgi服务时发生死锁,osgi,spring-dm,Osgi,Spring Dm,这个问题与使用SpringDM导入osgi服务时发生的死锁有关(有时如下所述) 我最近在SpringDM的ServiceDynamicInterceptor类中遇到了这个问题,它导致了死锁的情况。当从两个bundle加载两个应用程序上下文时,就会发生这种情况。假设应用程序ctx A导出osgi服务,而应用程序ctx B导入从A导出的osgi服务。当两个捆绑包一起启动时,就会出现问题。当app ctx A初始化时,spring在发布osgi服务期间同步调用为该服务注册的侦听器。。假设app ctx

这个问题与使用SpringDM导入osgi服务时发生的死锁有关(有时如下所述)

我最近在SpringDM的ServiceDynamicInterceptor类中遇到了这个问题,它导致了死锁的情况。当从两个bundle加载两个应用程序上下文时,就会发生这种情况。假设应用程序ctx A导出osgi服务,而应用程序ctx B导入从A导出的osgi服务。当两个捆绑包一起启动时,就会出现问题。当app ctx A初始化时,spring在发布osgi服务期间同步调用为该服务注册的侦听器。。假设app ctx B同时被初始化,并且osgi导入被执行。首先,它将osgi服务的侦听器添加到bundle上下文中,然后查找osgi服务。正如监听器被添加到bundle上下文中一样,app ctx A会将其拾取并执行监听器。此时,获取锁的app ctx B尝试查找在调用侦听器时尚未发布的osgi服务,该侦听器等待释放相同的锁,从而导致死锁。当SpringBean创建超时在5分钟内达到(默认值)后,应用程序ctx B将失败,BeanInitializationException由ServiceUnavailableException引起

我列出了在两个线程中执行的代码。请注意,查找和侦听器都是在同一个文件-ServiceDynamicInterceptor中定义的

应用程序Ctx A正在等待锁定

145: synchronized (lock) {
146:      servicePresent = (wrapper != null && wrapper.isServiceAlive());
147: }
App Ctx B正在等待osgi服务在发布

428: private Object lookupService() {
429:        synchronized (lock) {
430:              return (Object) retryTemplate.execute(retryCallback);
431:        }
432: }
正如我前面所说,当两个bundle一起重新启动时,就会发生这种情况。然而,由于明显的原因,这种情况并非每次都会发生。 我的问题是,是否有任何方法可以避免这种死锁

从线程转储中提取

应用程序Ctx A

"SpringOsgiExtenderThread-90" Id=908 in BLOCKED on lock=java.lang.Object@5a9a333f
     owned by pool-45-thread-1 Id=798
    at org.springframework.osgi.service.importer.support.internal.aop.ServiceDynamicInterceptor$Listener.serviceChanged(ServiceDynamicInterceptor.java:146)
    at org.apache.felix.framework.util.EventDispatcher.invokeServiceListenerCallback(EventDispatcher.java:934)
    at org.apache.felix.framework.util.EventDispatcher.fireEventImmediately(EventDispatcher.java:795)
    at org.apache.felix.framework.util.EventDispatcher.fireServiceEvent(EventDispatcher.java:544)
    at org.apache.felix.framework.Felix.fireServiceEvent(Felix.java:4596)
    at org.apache.felix.framework.Felix.registerService(Felix.java:3604)
    at org.apache.felix.framework.BundleContextImpl.registerService(BundleContextImpl.java:346)
    at org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean.registerService(OsgiServiceFactoryBean.java:310)
    at org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean.registerService(OsgiServiceFactoryBean.java:279)
    at org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean$Executor.registerService(OsgiServiceFactoryBean.java:95)
    at org.springframework.osgi.service.exporter.support.internal.controller.ExporterController.registerService(ExporterController.java:40)
    at org.springframework.osgi.service.dependency.internal.DefaultMandatoryDependencyManager.startExporter(DefaultMandatoryDependencyManager.java:320)
    at org.springframework.osgi.service.dependency.internal.DefaultMandatoryDependencyManager.checkIfExporterShouldStart(DefaultMandatoryDependencyManager.java:261)
    at org.springframework.osgi.service.dependency.internal.DefaultMandatoryDependencyManager.discoverDependentImporterFor(DefaultMandatoryDependencyManager.java:254)
      - locked org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean@2ae6baf0
    at org.springframework.osgi.service.dependency.internal.DefaultMandatoryDependencyManager.addServiceExporter(DefaultMandatoryDependencyManager.java:187)
    at org.springframework.osgi.service.dependency.internal.MandatoryDependencyBeanPostProcessor.postProcessAfterInitialization(MandatoryDependencyBeanPostProcessor.java:46)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1461)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
      - locked java.util.concurrent.ConcurrentHashMap@25dfde15
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:589)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.access$1600(AbstractDelegatedExecutionApplicationContext.java:69)
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$4.run(AbstractDelegatedExecutionApplicationContext.java:355)
      - locked java.lang.Object@c6d4820
    at org.springframework.osgi.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:320)
    at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:132)
    at java.lang.Thread.run(Thread.java:745)
应用程序Ctx B

"pool-45-thread-1" Id=798 in TIMED_WAITING on lock=java.lang.Object@2b767b9b
    at java.lang.Object.wait(Native Method)
    at org.springframework.osgi.service.importer.support.internal.support.RetryTemplate.execute(RetryTemplate.java:106)
    at org.springframework.osgi.service.importer.support.internal.aop.ServiceDynamicInterceptor.lookupService(ServiceDynamicInterceptor.java:430)
    at org.springframework.osgi.service.importer.support.internal.aop.ServiceDynamicInterceptor.getTarget(ServiceDynamicInterceptor.java:415)
    at org.springframework.osgi.service.importer.support.internal.aop.ServiceDynamicInterceptor.afterPropertiesSet(ServiceDynamicInterceptor.java:472)
    at org.springframework.osgi.service.importer.support.OsgiServiceProxyFactoryBean.createProxy(OsgiServiceProxyFactoryBean.java:215)
    at org.springframework.osgi.service.importer.support.AbstractServiceImporterProxyFactoryBean.getObject(AbstractServiceImporterProxyFactoryBean.java:86)
    at org.springframework.osgi.service.importer.support.OsgiServiceProxyFactoryBean.getObject(OsgiServiceProxyFactoryBean.java:161)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:102)
      - locked java.util.concurrent.ConcurrentHashMap@1a8ffb40
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1442)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:248)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1109)
    at org.apache.camel.spring.spi.ApplicationContextRegistry.lookup(ApplicationContextRegistry.java:43)
    at org.apache.camel.impl.CompositeRegistry.lookup(CompositeRegistry.java:51)
    at org.apache.camel.impl.PropertyPlaceholderDelegateRegistry.lookup(PropertyPlaceholderDelegateRegistry.java:62)
    at org.apache.camel.util.CamelContextHelper.lookup(CamelContextHelper.java:119)
    at org.apache.camel.model.RouteBuilderDefinition.createRouteBuilder(RouteBuilderDefinition.java:64)
    at org.apache.camel.core.xml.AbstractCamelContextFactoryBean.installRoutes(AbstractCamelContextFactoryBean.java:624)
    at org.apache.camel.core.xml.AbstractCamelContextFactoryBean.afterPropertiesSet(AbstractCamelContextFactoryBean.java:276)
    at org.apache.camel.spring.CamelContextFactoryBean.afterPropertiesSet(CamelContextFactoryBean.java:235)
    at org.apache.camel.osgi.CamelContextFactoryBean.afterPropertiesSet(CamelContextFactoryBean.java:64)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
      - locked java.util.concurrent.ConcurrentHashMap@1a8ffb40
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.context.event.AbstractApplicationEventMulticaster.getApplicationListeners(AbstractApplicationEventMulticaster.java:155)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:86)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:327)
    at org.springframework.osgi.service.importer.support.internal.aop.ServiceDynamicInterceptor.publishEvent(ServiceDynamicInterceptor.java:439)
    at org.springframework.osgi.service.importer.support.internal.aop.ServiceDynamicInterceptor.access$300(ServiceDynamicInterceptor.java:67)
    at org.springframework.osgi.service.importer.support.internal.aop.ServiceDynamicInterceptor$EventSenderRetryTemplate.onMissingTarget(ServiceDynamicInterceptor.java:96)
    at org.springframework.osgi.service.importer.support.internal.support.RetryTemplate.execute(RetryTemplate.java:95)
    at org.springframework.osgi.service.importer.support.internal.aop.ServiceDynamicInterceptor.lookupService(ServiceDynamicInterceptor.java:430)
      - locked java.lang.Object@5a9a333f
    at org.springframework.osgi.service.importer.support.internal.aop.ServiceDynamicInterceptor.getTarget(ServiceDynamicInterceptor.java:415)
    at org.springframework.osgi.service.importer.support.internal.aop.ServiceDynamicInterceptor.afterPropertiesSet(ServiceDynamicInterceptor.java:472)
    at org.springframework.osgi.service.importer.support.OsgiServiceProxyFactoryBean.createProxy(OsgiServiceProxyFactoryBean.java:215)
    at org.springframework.osgi.service.importer.support.AbstractServiceImporterProxyFactoryBean.getObject(AbstractServiceImporterProxyFactoryBean.java:86)
    at org.springframework.osgi.service.importer.support.OsgiServiceProxyFactoryBean.getObject(OsgiServiceProxyFactoryBean.java:161)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:102)
      - locked java.util.concurrent.ConcurrentHashMap@1a8ffb40
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1442)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:305)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:323)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
      - locked java.util.concurrent.ConcurrentHashMap@1a8ffb40
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:472)
      - locked java.lang.Object@62b8345f
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.access$301(AbstractDelegatedExecutionApplicationContext.java:69)
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$1.run(AbstractDelegatedExecutionApplicationContext.java:186)
    at org.springframework.osgi.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.normalRefresh(AbstractDelegatedExecutionApplicationContext.java:182)
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$NoDependenciesWaitRefreshExecutor.refresh(AbstractDelegatedExecutionApplicationContext.java:89)
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.refresh(AbstractDelegatedExecutionApplicationContext.java:175)
    at com.xxx.bbb.core.extender.service.bbbManagedServiceFactory$1.run(BbbManagedServiceFactory.java:178)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

过去,我在SpringDM中遇到过类似的问题,我所做的解决方法是通过
BundleActivator
使用
ServiceTracker
跟踪服务。在某些情况下,我还必须自定义依赖于该服务的所有代码(例如:自动布线)。它是丑陋的。。。但它奏效了。在做了一些类似的实验之后,我记得我还成功地使用了一个具有相同方法的
FactoryBean

在过去,我对Spring DM也有类似的问题,我所做的解决方法是通过
BundleActivator
使用
ServiceTracker
跟踪服务。在某些情况下,我还必须自定义依赖于该服务的所有代码(例如:自动布线)。它是丑陋的。。。但它奏效了。在做了一些类似的实验之后,我记得我还成功地使用了一个具有相同方法的
FactoryBean

你对这里的答案有什么期望?SpringDM已经多年没有维护了。因此,我认为你能达到的最大限度是一个变通办法。@ChristianSchneider一个变通办法会很好。我唯一可以避免这种情况的方法是添加一个延迟的bean(比如1s)并从应用程序ctx B中的osgi:reference元素中的depends-depend元素调用它。但如果在向应用程序ctx a添加更多bean时,应用程序ctx a需要更多的时间初始化,那么这种方法将不起作用。类似的问题在5年前提出。因此,这一问题从未得到解决。我后来才知道,声明性服务(DS)是更好的选择,因为它不依赖于Spring,并且有自己的组件模型和组件生命周期。这两种技术相辅相成。DS的功能集有点有限,但它是从OSGi的基础上编写的。所以所有涉及OSGi服务的东西都在DS中工作得最好。您希望从这里得到什么答案?SpringDM已经多年没有维护了。因此,我认为你能达到的最大限度是一个变通办法。@ChristianSchneider一个变通办法会很好。我唯一可以避免这种情况的方法是添加一个延迟的bean(比如1s)并从应用程序ctx B中的osgi:reference元素中的depends-depend元素调用它。但如果在向应用程序ctx a添加更多bean时,应用程序ctx a需要更多的时间初始化,那么这种方法将不起作用。类似的问题在5年前提出。因此,这一问题从未得到解决。我后来才知道,声明性服务(DS)是更好的选择,因为它不依赖于Spring,并且有自己的组件模型和组件生命周期。这两种技术相辅相成。DS的功能集有点有限,但它是从OSGi的基础上编写的。因此,所有涉及OSGi服务的东西都在DS中工作得最好。