gpt4 book ai didi

java - OSGi 'update' 命令;动态服务不会重启

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:17:20 25 4
gpt4 key购买 nike

我正在开发一个基于 OSGi 的系统,我打算在不关闭整个系统的情况下定期“更新”该系统。我打算使用“更新”来促进捆绑更改,因此编写了一个小应用程序(2 个 bundle )来尝试证明这一理论。

我的最终目标:我正在尝试实现一个可以使用 OSGi 动态更新 bundle 的平台。

到目前为止:我制作了 2 个 bundle ;一个 math 包(有 2 个可以加法和乘法的方法)和一个 display 包,它有一个每秒运行的线程,生成 2 个随机数并使用前面提到的 < em>math 将它们相加并相乘(并显示结果)。我正在使用声明性服务,因此在 math 包中有一个组件定义,它导出由接口(interface) IMath 定义的服务。同样,我在 display 包中有一个组件定义,它订阅(1:1 静态)由 IMath 接口(interface)定义的服务。我在每个组件的启动/关闭的每个阶段都有典型的调试消息。

当项目启动时,我通常会看到:

Starting up Math...
Starting up Display...
Running the Display thread...

然后每一秒我都会看到显示线程进行计算。此外,我可以执行以下操作(假设数学是包 1,显示是包 2)。

> stop 1
Stopping the Display thread...
Display bundle has been shut down.
Math bundle has been shut down
> start 1
Starting up Math...
Starting up Display...
Running the Display thread...

问题:到目前为止一切顺利,对吧?在我尝试使用“更新”命令之前,一切都很顺利。在这种情况下,我想更新 math 包,因为我在乘法计算中出错了。

> update 1
Stopping the Display thread...
Display bundle has been shut down.
Math bundle has been shut down
Starting up Math...

什么?为什么 ds 不调用我的启动方法来重新启动 display 包?我还尝试更新 display 包,它似乎工作正常。我的感觉是,如果您更新一个 bundle ,它会重新启动,但是任何从更新后的 bundle 订阅服务的 bundle 都将处于不确定状态。

更糟糕的是,如果我停止并启动 display 包,它仍然没有启动!

我很确定我看问题的方式是错误的,所以如果有人能阐明我的问题就太好了。如果有人想要源代码,请告诉我,我可以附上一些基本的 Java 文件来演示问题。

如果我对我的问题不够具体,请告诉我,我会进行推断。

感谢阅读!亚伦

最佳答案

我猜你没有在更新后进行刷新,IMath 是由数学包导出的?

如果您更新一个包,OSGi 不会让旧的类加载器消失。该加载器只能通过垃圾收集消失,即不再存在类引用。因此,当 bundle 1 更新时,它会创建一个 bundle 1',一个新的类加载器。但是,您的 bundle 2 仍然绑定(bind)到 bundle 1 类加载器。为防止类路径异常,OSGi 不会向 bundle 2 显示任何不兼容的服务。由于 bundle 1' 现在注册了一个 IMath' 服务 bundle 2 不再能看到这个服务,因为它寻找 bundle 1 的 IMath,它的类加载器仍然绑定(bind)到 bundle 1 for IMath。所以这是工作情况:

     +----+                +----+
| b1 |-------<|-------| b2 | <| service
+----+ v +----+ E exports package
\___E___[IMath]___I__/ I imports package

现在我们做一个更新:

        /----E--[IMath]---I--\
+----+ v +----+
| b1 | <| | b2 |
+----+ | +----+
| |
+-----------+

+----+
| b1'|-------<|
+----+ v
\___E___[IMath']

刷新操作会查看所有 bundle ,找出哪些 bundle 连接到“陈旧” bundle ,在本例中为 b2。然后它将停止 bundle 2,确保它对 b2 的类加载器的所有引用都被删除,然后使用新的类加载器再次启动 b2,以便它可以解析为 b1'。然后它将再次启动 b2,因为它是在刷新操作之前启动的:

                           +----+
+----| b2 |
| +----+
| |
+----+ | |
| b1'|-------<|--+ |
+----+ v |
\_______[IMath']______/

这通常会给人们留下疑问:什么……?为什么不结合更新/刷新?我该如何处理。

在 OSGi 1.0 中,我们对这个边缘阶段没有实际意义(我想我们没有意识到它的存在)。因此,在 OSGi 2 中,我们发现有些供应商很“急切”(将更新与刷新结合起来),有些供应商很懒惰(有些根本什么都不做)。更深入地思考它,我们意识到如果我们让它变得急切,大型更新集将变得非常低效,因为刷新需要大量工作。所以我们假设更新会像这样完成:

  1. 停止更新包
  2. 要更新的更新包
  3. 刷新
  4. 启动所有更新的包

通过这种方式,您可以最大限度地减少中断(更新的 bundle 仅停止/启动一次)并且 bundle 仅刷新一次。如果您查看 bnd launcher您将详细了解此模式(bnd 会自动更新在 IDE 中更改的包)。

现在,这种更新方式非常简单。然而,有些人喜欢生活在边缘并使用“优化”。首先,如果你有一个导出 IMath 的包 3,就不会有这个问题:

     +----+
| b1 |-I-\
+----+ |
| | +----+
^ [IMath]-E-| b3 |
| | +----+
+----+ |
| b2 |-I-/
+----+

在这种情况下,b1 的更新会很好,当 b1' 解析时它会找到 IMath 并且这会注册一个 IMath 服务,它恰好匹配 b2 的 IMath 类加载器(即 b3)。虽然这不那么具有破坏性,但它添加了一个额外的包,没有任何“合乎逻辑”的原因。就我个人而言,我认为提供者(即 b1)应该导出他们的契约(Contract) (IMath),因为他们与该契约(Contract)紧密耦合,不像通常享有向后兼容性的消费者。

关于java - OSGi 'update' 命令;动态服务不会重启,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17917633/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com