Java 如何帮助垃圾收集器?

Java 如何帮助垃圾收集器?,java,garbage-collection,jvm,Java,Garbage Collection,Jvm,我读过几篇关于垃圾收集工作原理的文章,但仍然不明白使用代是如何起作用的?据我所知,我们的主要想法是从最年轻的一代开始收集,然后转移到老一代。但是为什么这个想法的作者认为从最年轻的一代开始是最有效的方法呢?这一代人越老,意味着这个对象已经被使用了很多次,可能还需要再次使用。 删除最近创建的对象毫无意义,可能是它的临时(作用域:本地)对象。作者首先从最年轻的一代开始,因为这是在应用程序启动后首先填充的内容,但实际上,在应用程序运行的过程中,哪一代被扫描以及何时不确定 世代GC的要点是: 年轻一代使

我读过几篇关于垃圾收集工作原理的文章,但仍然不明白使用代是如何起作用的?据我所知,我们的主要想法是从最年轻的一代开始收集,然后转移到老一代。但是为什么这个想法的作者认为从最年轻的一代开始是最有效的方法呢?

这一代人越老,意味着这个对象已经被使用了很多次,可能还需要再次使用。
删除最近创建的对象毫无意义,可能是它的临时(作用域:本地)对象。

作者首先从最年轻的一代开始,因为这是在应用程序启动后首先填充的内容,但实际上,在应用程序运行的过程中,哪一代被扫描以及何时不确定

世代GC的要点是:

  • 年轻一代使用复制收集器将对象从eden和当前幸存者空间复制到其认为是空的空间(未使用的幸存者空间),因此速度快,GC暂停时间最小

  • 此外,大多数对象都会过早死亡,因此从伊甸园和当前幸存者空间复制少量幸存对象所需的暂停时间很小,因为只复制具有活动引用的对象,之后可以擦除伊甸园和之前的幸存者空间

  • 复制多次后,将对象复制到终身(旧)世代;最终,终身世代将填满,但是,这一次没有一个干净的空间来复制对象,因此垃圾收集器必须在世代内重新启动和压缩,这是缓慢的(与在eden和幸存者空间中执行的复制相比),意味着更长的暂停时间

  • 好消息是,基于大多数对象的启发,在应用程序的生命周期中,主要GC发生的频率要比次要GC发生的频率低得多

  • 还有一个好处是,所有新对象都分配在堆的顶部,这意味着这样做需要最少的指令,碎片整理作为复制过程的一部分自然发生

这两页,和,都描述了这一点。

读一下

使用不同的代,使得对象的分配变得简单和快速,因为大多数分配都是在Heap-Eden的单个区域中完成的。根据大多数对象因弱世代假设而过早死亡的观察结果,年轻世代的收集有更多的垃圾,这些垃圾将回收更多的内存,与堆相比,其相对较小,这意味着扫描对象所需的时间也较少。这就是年轻一代GCs速度快的原因


有关GC和生成的更多详细信息,请参阅

有许多短期对象;寿命较短的物体更容易被转移(积极使用),需要更多的治疗。考虑短时间内循环对象。在网上的其他地方做一个调查。一个很好的答案是文章长度。是的,但这取决于应用程序。我的意思是,我可以编写一个应用程序,在这个应用程序中根本不会有短生命的对象。如果是这样呢?(将其与数据库中额外的排序键/索引进行比较:无短期对象:快速完成。从旧一代开始,以另一种方式运行:大多数情况下,什么也不检查。处理短期对象是至关重要的。)如果您曾经在短循环中编写(字符串s:myStringList),然后创建一个短期的
迭代器。如果调用varargs方法也是一样的。将某些内容放入
哈希映射
会创建一个
条目
,该映射很可能会被丢弃或条目很快被删除。您可以编写一个应用程序来避免这一切,但这将是一个真正的混乱。可能需要再次?谁来决定?统计数据,假设你需要一个对象obj,在整个应用程序中,应用程序正在运行,在GC运行的前三次,obj正在使用中,它现在有第三代了,下次即使obj没有使用,GC也会运行。它很有可能再次需要。下次应用程序需要它时,为什么还要冒险再次加载它呢。我宁愿留着它。删除最不常用的句子。@nikhill57最后两句是错的。如果再次需要某个对象,则无法将其移除。它应该是这样的:为什么要浪费时间来确定是否可以删除旧对象。如果仍然有一个对某个对象的引用,那么它可能是“再次需要”—就这么简单。对象图是从GC根走出来的,该图中的任何对象都不是垃圾,其他所有对象都是垃圾。