尝试查找这个,但是我遇到的所有问题/答案都谈到了拥有2个幸存者空间的目的。我想了解拥有幸存者空间的一般目的。将物体从伊甸园移动到幸存者有什么好处?
表演
一般来说,拆分堆(可以是那一代或任何其他鉴别器)被视为一件相当好的事情,但并非所有收集器都遵循这一点(例如,Shenandoah
不是这样的收集器)。
为什么这是好事?扫描整个堆以查找活动对象需要时间。你如何告诉你的垃圾收集器——“现在该运行了”。什么时候?你可以说:每分配100个对象就运行一次。是不是太早了?(如果这些对象的大小只是堆的一小部分)或者更糟的是:是否为时已晚?如果您说:以堆占用率的65%触发一个集合(默认情况下,G1
会以该百分比触发一个主要集合,以及其他可能性)。如果在这65%的情况下,你发现大多数对象本应该更早地被收集,它们在堆中停留的时间太长了怎么办。
您可以看到这很快变得复杂。当您了解扫描堆需要时间时,情况会变得更糟,并且您最不想让您的应用程序在GC运行时停顿。但也请记住,有些收集器会自动扫描堆,因此他们没有这个问题(shenandoah
、ZGC
或C4
)。
如果可以分离堆,则只需扫描其中的一部分,因此只需花费很少的时间。人们称之为“小”收藏。因此,一些收藏家将堆分为“年轻”和“老年”,这种区分是以“婴儿死亡率”为前提的:年轻的物体很快就会死亡。因此,如果这样做,年轻的对象很快就会死亡,那么只能扫描堆的特定部分,并且在大多数情况下只能处理该部分。这也简化了以下问题的答案:GC应该何时运行?当然,当young吃饱的时候。
现在请直截了当地说:为什么需要一个幸存者呢。让我们假设它不在那里。第一个GC循环发生(young区域已满,确切地说,我们称之为伊甸园),接下来会发生什么?GC需要知道那里还有什么,把它移到“老一代”,清除Eden
,然后重新开始分配。第二个周期到来,做同样的事情,以此类推,直到GC说:“老一代如果满了,我就不能再动了。”。这是一个著名的“老一代”发生的地方。通常很贵。
但我们确实知道这里的“婴儿死亡率”。我们确实知道第二和第三个GC周期将一些对象转移到第四阶段收集的旧一代。这个机会被错过了。因此:幸存者空间。它将对象保留在那里的时间比单个GC周期(称为幸存者年龄)“长一点”,因为它知道在最近的将来这将成为垃圾。因此,无需经常扫描旧的,只需扫描并处理堆的一小部分(Eden
和Survivor
)。至于为什么有两个Survivor空间,这是另一个问题......
实际上,最新的地面军事系统并不需要这些。他们找到了一种在应用程序运行时同时扫描堆的方法,因此他们没有这些空间。年轻死亡的前提仍然存在,一些GC算法可能会使用这个前提;现在或将来。
我们的服务器应用程序似乎在一段时间内表现正常,但过了一段时间后,生存空间将填满100%,从那时起,堆使用量增加,GC周期(次要和主要)变得越来越频繁,最终堆耗尽。 这是“jstat-gcutil”的一部分 我的问题是这种应用程序行为背后的主要原因是什么?是太小的年轻空间或堆,其他一些JVM参数,还是只是一个普通的旧内存泄漏? 解决这个问题的最佳策略是什么,GC调优还是应用程序重构? JDK 1.6
我有一个JVM进程,最大1024 MB堆大小的核心转储。(OpenJDK 7 on linux) 当我使用YourkitJavaProfiler 10.0.6分析核心转储文件时,我发现进程仅在内存不足时使用803 MB堆。 似乎两个幸存者堆使用了堆的2/9(或保留)。 我在Windows7上用JDK7进行了测试,jvisualvm(带有Visual GC插件)显示一个幸存者的大小是伊甸园大小的1/
问题内容: 对于Sun / Oracle的JVM,我读过GC算法将新一代划分为一个伊甸园区域和两个幸存者区域。我想知道的是,为什么有两个幸存者地区而不是一个?该算法可以在伊甸园和一个幸存者区域之间保持乒乓(目前它在两个幸存者区域之间的方式);或这种方法有什么缺点? 问题答案: 我相信JRockit的GC实现更像您建议的那样工作,只有一个eden和一个幸存者空间,但请不要在此引用我。 HotSpot
在JVM重启之前,java(8)内存容量是否会减少? 我正在使用jstat-gc转储内存信息,下面是两天的快照。与第一个快照相比,第二个快照对SC1和EC的资本金更少。 有人能帮助/解释为什么我看到这种行为吗?这是预期的吗?
你能回答我一个关于JVM垃圾收集过程的问题吗? 为什么堆被分为伊甸园、幸存者空间和老一代? 当一个年轻的疏散被处理时,通过从根开始的引用访问对象,以找出无法到达的对象。可到达的对象标记为“活动”,不可到达的对象不标记,将被删除。 因此,所有对象都会被考虑,包括旧一代中分配的对象也会被访问并标记是否可以访问。 据我所知,同时回收年轻一代和老一代是非常困难的,因为这两代人位于内存中不同的连续部分。 但
Java虚拟机在执行的时候会把管理的内存分配到不同的区域,这些区域称为虚拟机内存;同时对于虚拟机没有直接管理的物理内存,也会有一定的利用,这些被利用但不在虚拟机内存的地方称为本地内存。 JVM内存:受虚拟机内存大小的参数控制,当大小超过参数设置的大小时会报OOM。 本地内存:本地内存不受虚拟机内存参数的限制,只受物理内存容量的限制;虽然不受参数的限制,如果所占内存超过物理内存,仍然会报OOM。 虚