【问题标题】:How to check if a class in an OSGi bundle has been correctly unloaded?如何检查 OSGi 包中的类是否已正确卸载?
【发布时间】:2015-11-06 09:50:48
【问题描述】:

我有一个应用程序,我怀疑它会泄漏一些类引用。

为了揭露这种错误行为,我们编写了一个测试:BundleUnloadIT

在那个测试中,我使用了

    Assertions.assertThat(weakReference.isEnqueued())
        .as("weak reference should have been enqueued, but is not").isTrue();

测试我的引用是否正确 gc'ed。 但无论我尝试做什么,引用永远不会排队。 所以我怀疑对该类的某些引用在某处泄漏。

那么...我是否使用正确的方法来测试我的类是否已卸载?

如果没有,我该如何正确地进行测试?

如果是,则在某处泄漏了参考。我怎样才能找到它?

【问题讨论】:

  • “但无论我尝试做什么,引用都不会入队”,那么,你尝试了什么?

标签: java garbage-collection osgi classloader


【解决方案1】:

如果类的类加载器没有被强引用(也就是说,类的类加载器也可以被垃圾回收),则只能卸载(垃圾回收)类。只有当它加载的所有类都没有被强引用时,类加载器才能被垃圾回收。所以这是一个全有或全无的命题。每个类都有对其类加载器的强引用,并且每个类加载器对其已加载的所有类都有强引用。因此,如果类加载器加载的任何类被强引用,则不可能对类进行垃圾回收。

【讨论】:

  • 好的,但我打电话给osgi.uninstall(bundle); 时不就是这样吗?因为,当我查看该测试时,在我看来,我没有保持对 Class 对象的强引用(好吧,除了我希望该测试公开的那个)。
  • OSGi 中的 bundle.uninstall 不会强制卸载任何类,因为在 JVM 中无法做到这一点。它向包发送一个停止信号,并且包实现应该清理它正在做的任何事情。但是一个执行不佳的包仍然可以挂在引用上并阻止垃圾收集。造成这种情况的一个常见原因(但不是唯一原因)是当一个包启动一个线程但在停止信号发生时未能正确终止该线程。
  • @NeilBartlett 好的,在我们的例子中,包不启动线程,包由 Apache Felix 管理。所以...应该发生什么?类对象是否应该是永久的并且永远不会被 GC 处理?
  • @Riduidel 不,不是。抱歉,如果没有更多数据,我无法告诉你发生了什么。请记住,GC 并不是完全可以预测的野兽,它可能只是因为缺乏内存压力而决定不需要清理您的类。
  • @Riduidel 我有同样的问题。我实现了一个“动态”捆绑安装/卸载过程。就我而言,我发现确保加载所有新类的唯一方法(包括与先前加载的类同名、在同一个包中的类)是重新启动 Apache Felix。
猜你喜欢
  • 2016-03-23
  • 2019-01-20
  • 2013-10-02
  • 2014-11-07
  • 2015-01-13
  • 2019-12-28
  • 1970-01-01
  • 2015-10-18
  • 2020-08-04
相关资源
最近更新 更多