在 JavaFX 8 中防止对中间绑定进行垃圾回收的推荐方法是什么?

2022-09-02 14:08:40

TL;DR:GC正在吃掉我的活性结合。

我有一个应用程序是在Java 7上使用JavaFX 2.2开发和成功部署的。

当我升级/过渡到 JavaFX 8.0(和 Java 8)时,某些功能将“神秘地”停止工作 - 应用程序生命周期中期 - 没有例外或错误状态更改的其他迹象。例如;按钮停止工作,自定义单元格渲染器停止应用,启用/禁用状态停止更新。

经过几个小时的挖掘,我想我已经将问题追溯到我所理解的JavaFX 8中的一些变化以及内部使用来处理JavaFX 2.2中的内存泄漏。基本上,我正在创建的用于管理数据状态依赖项的绑定似乎正在被垃圾回收,尽管它们控制的 s 仍然处于活动状态。javafx.beans.WeakListenerNode

当我使用匿名类实例化绑定时,最常出现的问题似乎会出现。通过将对绑定的引用存储为类成员,可以解决我的一些(但不是全部)问题,从而防止 GC 收集它。我甚至让整个控制器都得到了GC'd,因为它们是通过FXML加载实例化的,从来没有直接引用过(我现在总是在父节点的属性中填充对控制器的引用)。userData

我的问题是:

  1. 相关的错误以非确定性方式出现(或者至少是内存占用的函数,
  2. 如果应该避免使用匿名类的绑定,那么在大型现有代码库中找到每个实例来更改它需要做很多工作。
  3. 即使我能找到每个实例,它也会使代码变得非常混乱

令人沮丧的是,我似乎在Oracle文档中找不到任何说“不要使用匿名类创建绑定”的内容,或者任何其他确保可靠使用绑定的准则。许多代码示例都使用匿名类绑定。我也找不到任何关于如何将JavaFX 2.2应用程序正确更新到JavaFX 8的说明。

开发非平凡的JavaFX应用程序的人的任何建议都非常感谢(我已经开发了3年的JavaFX 2.x应用程序,而Swing应用程序>15年,所以这并不是一个n00b问题)。


注意:我的问题类似于 Clean JavaFX 属性侦听器和绑定(内存泄漏),但我想知道具体和明确地知道如何使用复杂的绑定,并确保它们不会在随机时间被垃圾回收,而不会诉诸于对每个实例的引用的污染类。


答案 1

WeakEventHandler应该允许侦听器对象的GC(如果它没有被其他引用)并在那时停止工作。正如您所发现的,这意味着只要您需要它来继续触发,就必须引用该处理程序。此要求或多或少独立于您是否使用匿名类;如果您使用普通类,它将以相同的方式失败。

没有办法“自动”确定将来不会再触发某个事件,这本质上是“修复”此问题的功能请求所需要的。如果您不想要任何GC'd,您只需将所有匿名侦听器添加到某个位置存储为静态变量的列表中即可。如果您希望GC工作(最终您将工作),则必须通过仅在需要时维护引用并在不再需要时释放它们来控制它。


答案 2

推荐