这种技术是否可以防止Java进行垃圾收集?

时间:2018-09-27 23:06:25

标签: java garbage-collection

科特·麦卡利斯({@ 3}}

其要旨如下:

  1. 加载应用程序时,实例化应用程序 在将来的某个时刻可能需要的未使用对象/类的池。
  2. 当您要实例化一个新对象时,请在您的池中找到一个未使用的适当类型的对象,抓住它并设置其属性。
  3. 改为使用此对象。
  4. 完成后,将其标记为“未使用”,以便以后的方法可以使用它。

我的问题是,这种方法是否也可以与Java垃圾收集器一起使用,或者是否更棘手,并且最终只能扫描整个堆或其他内容。

这主要是理论/好奇心。我在开发中没有依赖于规避垃圾收集的应用程序。

1 个答案:

答案 0 :(得分:4)

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

  1. 如果执行不正确,将导致内存泄漏。问题是“池”需要保留对其所有对象的引用。这样可以防止随后被垃圾回收。但是,如果应用程序在完成对对象的处理后始终无法将其标记为“未使用”(例如错误),则这些对象将永远保持“使用中”。

    (如果您尝试使用Reference对象之类的东西来减轻这种情况,则会最终占用更多空间,并给GC带来更多负担。)

  2. GC确实运行时,它必须遍历池中的所有对象以及它们的所有从属对象。这比允许对象死亡的工作要多。 (根本不需要扫描年轻的无法到达的物体。)

  3. 经过几个GC周期后,您的池中的对象将被保留,因为它们的寿命很长。这意味着它们将趋向于导致短期依赖的对象,这些对象本来可以收集起来,直到收集旧堆为止。同样,对保有权对象字段的引用分配可能会更昂贵,并且可能会使年轻空间的收集花费更长的时间(由于旧的->年轻引用)。

请注意,通常会建议/完成您正在谈论的对象池类型,以减轻应用程序中过多的GC暂停。在典型的现代JVM中,有些GC专门设计用于最大程度地减少暂停。低暂停收集器是解决 most Java应用程序中此问题的更好选择。 (高度互动的游戏是例外,在这种游戏中,任何形式的“滞后”都是无法接受的。)

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

  • 处理初始化非常昂贵的对象。
  • 处理需要限制数量的对象。
  • 处理与需要适当管理的外部资源关联的对象。

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