在 JavaFX 8 中防止中间绑定被垃圾收集的推荐方法是啥

Posted

技术标签:

【中文标题】在 JavaFX 8 中防止中间绑定被垃圾收集的推荐方法是啥【英文标题】:What is the recommended approach to keeping intermediate bindings from being garbage collected in JavaFX 8在 JavaFX 8 中防止中间绑定被垃圾收集的推荐方法是什么 【发布时间】:2015-03-28 18:36:23 【问题描述】:

TL;DR:GC 正在吞噬我的活动绑定。

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

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

经过数小时的挖掘,我想我已经将问题归结为我理解的 JavaFX 8 的一些变化以及 javafx.beans.WeakListener 的内部使用以处理发现的 JavaFX 2.2 中的内存泄漏。基本上,我为管理数据状态依赖性而创建的绑定似乎正在被垃圾收集,尽管它们控制的Nodes 仍然处于活动状态。

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

我的问题是:

    相关的错误是不确定地出现的(或者至少是内存占用的函数, 如果应避免通过匿名类进行绑定,则需要在现有的大型代码库中找到每个实例来更改它 即使我能找到每一个实例,代码也会非常混乱

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

非常感谢开发非平凡 JavaFX 应用程序的人的任何建议(我开发 JavaFX 2.x 应用程序已有 3 年,Swing 应用程序开发超过 15 年,所以这是t 完全是一个 n00b 问题)。


注意:我的问题类似于Clean JavaFX property listeners and bindings (memory leaks),但我想具体而明确地知道如何使用复杂绑定并确保它们不会在随机时间被垃圾收集,而不使用引用每个实例的污染类.

【问题讨论】:

您能否详细说明“JavaFX 8 的变化和 javafx.beans.WeakListener 的内部使用”,因为我不知道这些(诚然,拒绝对 fx pre 8 进行深入研究; -) - 根据我的经验,垃圾收集绑定一直是(现在仍然是)令人讨厌的...... 对于那些寻找简单示例的人,请参阅this question。您想要做的是使任何绑定的生命周期与依赖它的任何 UI 元素相同(这会很棘手)。 是的,刚刚测试过,在另一个问题中,JavaFX 2.2 和 JavaFX 8 似乎都出现了“丢失绑定”问题...... 诚然,我的代码在 2.x 中工作的事实可能是一个红鲱鱼; GC 行为和内存占用在 Java 8 中可能会有所不同,从而产生影响。 您在文档中没有找到这样的警告并不让我感到惊讶。这意味着有人考虑了弱听者的含义,好吧,如果有人考虑过,弱听者的想法立即被放弃了。但是,嘿,我希望这是 JavaFX 设计中唯一的坏主意…… 【参考方案1】:

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

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

【讨论】:

这个问题有 19 票,而唯一的答案只有 3 票,尽管被接受为解决方案。这似乎不成比例,让我怀疑这个答案。有很多人觉得这个问题很好,但唯一的答案不太好? Atsby,距离这个答案已经过去了五年(显然你最后一次出现在这里),你知道你自己的答案有任何弱点吗?

以上是关于在 JavaFX 8 中防止中间绑定被垃圾收集的推荐方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

线程防止所有者的垃圾收集

绑定会在 WPF 中造成内存泄漏吗?

JVM垃圾收集器

垃圾收集需要很长时间[如何调试收集的内容?]

简单说明PHP的垃圾收集机制是怎样的?

android 垃圾回收机制