为了账号安全,请及时绑定邮箱和手机立即绑定

这种技术是否会阻止 Java 进行垃圾收集?

这种技术是否会阻止 Java 进行垃圾收集?

慕侠2389804 2021-10-17 17:04:23
Colt McAnlis 制作了一个非常有趣的视频,内容是防止 JavaScript 垃圾收集器减慢应用程序速度它的要点如下:当应用加载时,实例化一个未使用的对象/类池,你的应用在未来的某个时候可能需要这些对象/类。当您想实例化一个新对象时,请在池中找到一个未使用的适当类型的对象,抓取它并设置其属性。改用这个对象。完成后,将其标记为“未使用”,以便将来的方法可以使用它。我的问题是这种方法是否也适用于 Java 垃圾收集器,或者它是否更难规避并且最终只会扫描整个堆或其他东西。这主要是理论/好奇的事情。我没有任何依赖于规避垃圾收集的应用程序正在开发中。
查看完整描述

1 回答

?
慕斯王

TA贡献1864条经验 获得超2个赞

从某种意义上说,它会“起作用”。但不建议这样做,因为存在一些重大问题。

  1. 如果你错误地实现了这一点,那就是内存泄漏。问题是“池”需要保留对其所有对象的引用。这可以防止被垃圾收集。但是,如果应用程序在处理完对象后未能始终将对象标记为“未使用”(例如错误),则这些对象将永远“使用中”。

    (如果您尝试使用诸如Reference对象之类的东西来缓解这种情况,您最终会使用更多空间,并在 GC 上放置更多负载。)

  2. 当 GC 确实运行时,它必须遍历池中的所有对象,以及它们的所有依赖对象。这比允许对象消亡的工作量更大。(根本不需要扫描年轻的无法访问的对象。)

  3. 经过几个 GC 周期后,池中的对象将被永久使用,因为它们是长期存在的。这意味着它们将倾向于导致短期依赖对象,否则这些对象可能会被保留,直到旧堆被收集为止。此外,对老对象字段的引用分配可能更昂贵,并且可能使年轻空间集合花费更长的时间(因为旧 -> 年轻引用)。

请注意,您所谈论的对象池类型通常是为了减少应用程序中过多的 GC 暂停而提出/完成的。在典型的现代 JVM 中,有专门设计用于最小化暂停的 GC。在大多数Java 应用程序中,低暂停收集器是解决此问题的更好选择。(一个例外是高度互动的游戏,其中任何类型的“滞后”都是不可接受的。)

使用对象池还有其他原因:

  • 处理初始化开销很大的对象。

  • 处理需要限制数量的对象。

  • 处理与需要正确管理的外部资源相关联的对象。

示例包括线程池、数据库连接池和 HTTP 连接池(在典型的 HTTP 客户端库中)。这些在适当的情况下绝对是有益的。


查看完整回答
反对 回复 2021-10-17
  • 1 回答
  • 0 关注
  • 138 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信