假设我有一个包含组件 B 的 Bundle A,它不是 Export-Package 的一部分。一旦激活,该组件将自行安排定期运行。调度程序由另一个包提供。
我的问题是,如果我在组件 B 正在由调度程序的线程池中的线程运行时卸载 Bundle A,这将意味着什么?线程会继续运行吗?还是线程会抛出异常?
捆绑包有一个生命周期。当捆绑包处于活动状态时,它将在卸载之前停止。如果“组件 B”是声明式服务组件,它也会被停止。如果没有,那么至少会触发捆绑激活器中的 stop 方法。
在停止期间,您(作为组件 B 的提供者)负责从计划中取消计划组件,以便将其从线程池中删除。如果线程当前正在运行,那么您应该实现一个取消功能,以便可以中止它。
如果您没有正确清理(即取消计划/取消线程),则可能会再次执行该线程。如果您从该线程中访问 OSGi API,那么您将获得 IllegaleStateException(对于某些 API 使用,因为捆绑包的 BundleContext 在停止后变得无效)。但是,如果不是,那么您的线程可能会继续永远运行。对象和内存不会被释放。类和捆绑类加载器不会被垃圾收集。因此,正确实施“停止”非常重要。
如果您使用代理引用在模块之间进行绑定,则在您替换模块之前,这些代理可能无效。
如果您有直接绑定,则“未安装”模块不会真正删除,直到它没有在任何地方使用。您可以替换它,新用途将使用新库。
OSGi 中没有魔法,对对象的现有引用被维护并防止垃圾收集器获取相应的类加载器。
幸运的是,DS 让相应的清理工作变得非常容易。