你能回答我一个关于JVM垃圾收集过程的问题吗?
为什么堆被分为伊甸园、幸存者空间和老一代?
当一个年轻的疏散被处理时,通过从根开始的引用访问对象,以找出无法到达的对象。可到达的对象标记为“活动”,不可到达的对象不标记,将被删除。
因此,所有对象都会被考虑,包括旧一代中分配的对象也会被访问并标记是否可以访问。
据我所知,同时回收年轻一代和老一代是非常困难的,因为这两代人位于内存中不同的连续部分。
但是,如果即使在Young疏散级别上进行最简单的标记之后,如果所有可达和不可达的对象都是已知的并且可以删除的,那么我们为什么需要这种划分呢?
我也知道弱世代假说,但为什么我们需要分裂?
如果你考虑搬家,这个部门非常有用。如果没有分离,一个年轻的集合将在堆中留下很多漏洞,需要自由列表管理或压缩旧的一代。
另一方面,如果年轻一代作为半空间GC实施,则无需进行此类清理和跟踪,因为根据定义,疏散空间仅包含少量收集后的死物,因此可被视为之后的自由空间。这还可以在年轻一代中分配凹凸指针。
基本前提是,当创建新对象时,不存在从旧对象到新对象的引用,对于许多对象,甚至大多数对象,这一点永远不会改变。这意味着,如果可以证明仍然没有从旧对象到新对象的引用,或者当您确切地知道创建了哪些引用时,您可以只扫描年轻一代进行“次要”垃圾收集。
这意味着必须跟踪和记住对旧对象的引用更改(但请记住这样的前提,即此类更改不会经常发生)。
一个实施策略是卡片标记:
如果垃圾收集器没有收集整个堆(增量收集),垃圾收集器需要知道从堆的未收集部分到正在收集的堆部分的指针在哪里。这通常适用于一代垃圾收集器,其中堆的未收集部分通常是老一代,而堆的收集部分是年轻一代。保存这些信息的数据结构(老一代指向年轻一代对象的指针)是一个记忆集。牌桌是一种特殊的记忆装置。Java HotSpot VM使用字节数组作为卡表。每个字节都被称为一张卡。卡片对应于堆中的一系列地址。脏卡意味着将字节的值更改为脏值;脏值可能在卡覆盖的地址范围内包含从老一代到年轻一代的新指针。
处理卡片意味着查看卡片,看看是否有旧代到年轻代的指针,并可能对该信息做一些事情,例如将其传输到另一个数据结构。
当然,如果能让我们在扫描过程中跳过某些内存区域,并且维护这些记忆集不会超过节省的成本,那么使用世代只会带来好处。
SurvivorRatio参数控制两个幸存者空间的大小。例如,-XX:SurvivorRatio=6将每个幸存者空间和eden之间的比率设置为1:6,每个幸存者空间将是年轻一代的八分之一。 为什么幸存者和伊甸园的空间容量与SurvivorRatio不匹配,如下所示?由制作。
在JVM重启之前,java(8)内存容量是否会减少? 我正在使用jstat-gc转储内存信息,下面是两天的快照。与第一个快照相比,第二个快照对SC1和EC的资本金更少。 有人能帮助/解释为什么我看到这种行为吗?这是预期的吗?
这是来自太空的100%新的伊甸园--一个问题吗? 我的JAVA选项是:-xms10240m-xmx14336m-xx:permsize=192m-xx:maxpermsize=256m-xx:newsize=8192m-xx:maxnewsize=8192m-xx:-disableexplicitgc-xx:+useconcmarksweepgc-xx:cmsinitiatingoccupancy
G1GC老一代提交的堆随着时间的推移而上升(生产时大约5到6天)但老一代使用的堆没有。伊甸园和幸存者堆被迫减少到最低限度(总堆的5%),因此垃圾回收机制,因为越来越频繁。应用程序在一开始就缓存了一个大对象图,然后在整个运行生命周期中拥有其他时间/使用有限的缓存。它具有相当高的对象创建率,但除了缓存的对象之外,并没有向老一代推广其中的很多内容。 我已经通过gceasy运行了GC日志。io,您可以看到
出于某种原因,G1决定增加提交的旧一代内存(尽管使用的内存没有增加),并减少Eden一代提交的内存(从而减少可用空间)。这似乎导致GC年轻一代的运行激增,并使应用程序在一段时间内没有响应。 我们还可以看到CPU使用率和机器中提交的虚拟内存总量(比物理内存总量还要大)出现峰值。也可能会看到磁盘使用率和swapout/swapin的激增。 我的问题是: G1决定减少Eden的大小并大幅增加老一代的pr
我们的服务器应用程序似乎在一段时间内表现正常,但过了一段时间后,生存空间将填满100%,从那时起,堆使用量增加,GC周期(次要和主要)变得越来越频繁,最终堆耗尽。 这是“jstat-gcutil”的一部分 我的问题是这种应用程序行为背后的主要原因是什么?是太小的年轻空间或堆,其他一些JVM参数,还是只是一个普通的旧内存泄漏? 解决这个问题的最佳策略是什么,GC调优还是应用程序重构? JDK 1.6