在JavaFX 8中保持中间绑定不被垃圾收集的建议方法是什么?

met*_*sim 19 java javafx java-8 javafx-8

TL; DR:GC正在吃我的活动绑定.

我在Java 7上使用JavaFX 2.2开发并成功部署了一个应用程序.

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

经过几个小时的挖掘,我想我已经将问题跟踪到了我所理解的JavaFX 8中的一些变化以及javafx.beans.WeakListener处理已发现的JavaFX 2.2中的内存泄漏的内部用法.基本上,似乎我正在创建的用于管理数据状态依赖性的绑定正在收集垃圾,尽管Node它们控制的s仍处于活动状态.

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

我的问题是:

  1. 相关的错误是非确定性的(或者至少是内存占用的函数,
  2. 如果应该避免通过匿名类进行绑定,那么在大型现有代码库中查找每个实例来进行更改是很多工作
  3. 即使我能找到每个实例,它也会极大地混乱代码

令人沮丧的是,我似乎无法在Oracle文档中找到"不要使用匿名类创建绑定"或任何其他确保可靠使用绑定的指南.很多代码示例都使用匿名类绑定.我也无法找到有关如何将JavaFX 2.2应用程序正确更新为JavaFX 8的任何说明.

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


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

Ats*_*sby 3

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

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