从捆绑上下文中检索OSGi服务的实例后,当服务停止时它是否会失效?
我的初步测试显示即使在服务包停止后也可以使用服务实例,这与我对OSGi的动态特性的理解相矛盾。
我想这可以归结为从OSGi容器中的另一个包中检索服务(通过ServiceTracker)实际上是什么,它是创建一个新实例还是它给你一个指向容器中注册的实例的指针?
服务停止后使用服务实例是否有任何危险?
答案 0 :(得分:5)
这是一个非常好的问题,所以我深入研究了规范,寻找明确的答案。事实证明,整个部分都在谈论这个问题 - 请参阅OSGi Service Platform Core Specification, Release 4, Version 4.2第132页开始的 5.4陈旧引用部分。
根据规范回答您的问题:
未定义的服务的行为未定义。这样的服务 可以继续正常工作或自行决定抛出异常。
并防止潜在的问题:
Bundles必须侦听Framework生成的事件以清理和删除陈旧 引用。
该规范还提供了一些如何最大限度地减少过时参考的后果的技巧。
答案 1 :(得分:2)
你说得对,它与OSGi的动态性质相矛盾。我相信虽然OSGi容器和服务本身的不同实现可能表现不同,但无法保证该服务可用。
例如,如果服务是使用Spring DM创建并注册的,那么检索的服务实际上是基于Spring的底层实现代理,实现仍然可以消失。因此,直接引用实现的服务引用可以防止该对象被删除,而基于代理的引用则不会。
答案 2 :(得分:1)
OSGi规范说:
捆绑包是可见的实体 在正常的应用程序编程对于 例如,当一个包停止时,全部 它的服务将被取消注册。
因此,您无法从已停止的捆绑包中获取服务。但从技术上讲,它可以使用它,至少只要你持有对服务对象的引用(没有人可以把它从你身上拿走而且它不会被GC)。但我认为使用该服务并不节省。它可能依赖于捆绑已停止后不可用的其他捆绑资源。
答案 3 :(得分:1)
一旦OSGi服务的实例是 从bundle上下文中检索到了 它在服务时失效 停了?
不,引用本身不会失效。只要容器中的东西拿着它,它也可能不是GC。
但是,它是否仍然有用,仅取决于服务实现本身,而不是容器。
我的初步测试显示即使在服务包>停止后也可以使用服务实例,这与我对OSGi的动态性质的理解相矛盾。
规范本身表明不应该持有这样的引用,但是由实施者来负责正确地实施规范;意味着没有矛盾,只有你可以根据规范实现和部署行为不正确的捆绑。
我想这可以归结为从另一个包中检索服务(通过ServiceTracker)的内容 在OSGi容器实际上,它是创建一个新实例还是它给你一个指针 到容器中注册的实例?
除非涉及ServiceFactory,否则容器不会创建新的服务实例(请参阅规范)。查找服务应始终为您提供指向容器中已注册实例的指针。
服务停止后使用服务实例是否有任何危险?
这仅取决于服务实施;但是,通过在捆绑中执行此操作,您将自动创建一个不符合规范的捆绑包。
在实践中,许多服务都是为了释放资源和参考而实施的,并且不再适当地响应。
答案 4 :(得分:0)
关于您的问题,在服务停止后使用服务实例是否有危险。引用4.2核心规范(5.4陈旧参考文献):
成为的服务的行为 未注册未定义。这样 服务可能会继续正常运作 或者在他们身上抛出一个例外 决定。
我不想在这里引用规范的整个部分,但以下句子是关于使用陈旧引用的危险的一个很好的讨论:
陈旧引用是对所属Java对象的引用 到已停止或关联的bundle的类加载器 使用未注册的服务对象。标准Java没有 提供任何通用的方法来清理陈旧的引用和捆绑 开发人员必须仔细分析他们的代码以确保陈旧 引用被删除。
过时的引用可能有害,因为它们会阻碍Java 收集类的垃圾收集器,可能还有实例, 停止捆绑。这可能会导致内存显着增加 用法并可能导致更新本机代码库失败。捆绑使用 强烈建议您使用服务跟踪器或服务跟踪器 声明性服务。
答案 5 :(得分:0)
永远不应将服务引用保留为引用。您应该始终在运行时查找服务。这与OSGI api有关,但并不总是需要它。
看一看 - OSGI serviceTracker - OSGI声明性服务 - OSGI BluePrint - 春天DM - Peaberry - iPojo
所有这些都为你提供了动力,其中大多数都没有使用OSGI api。
此致
Leen Toelen