GC heap 简述

[原]java gc与heap内存简述

2014-7-9阅读72 评论0

java内存结构和gc算法有很多种,二者也是互相决定的;使用不同的gc算法的jvm会有不同的内存结构。这里就简单整理下常见的sun jvm内存结构和回收算法。

一、java的内存结构

java的内存分为如上几块。

Virtual:如果 -Xms指定的值比-Xmx的小,那么两者的差值就是图上所示的virtual区域

Perm:永久区,主要用来放JVM自己的反射对象,比如类对象和方法对象等。对于spring hibernate这些需要动态类型支持的框架,这个区域需要足够的空间。这个区域不属于heap中。

Young:这里是较新的对象活跃区域。新创建的对象处于Eden区中,经过一次回收的对象会转移到From区;From区再经过一次回收会转移到To区;To区再经过一次回收就会移出Young区转移至Tenured(Old)区。

Tenured(Old):这里是经过数次GC后仍然存活的对象所处区域,池对象(如线程池)就活跃在这个区域中。

二、java gc机制

由于垃圾收集算法在各个虚拟机以及不同的平台上会有不同的实现,所以这里只大概记录一下几个基本的算法。

1.引用计数:

为每一个对象添加一个计数器,计数器记录了对该对象的活跃引用的数量。如果计数器为0,则说明这个对象没有被任何变量所引用,即应该进行垃圾收集。
收集过程如下:
1. 减少被收集对象所引用的对象的计数器的值
2.将其放入延时收集队列之中

引用计数的方法需要编译器的配合。编译器需要为此对象生成额外的代码。如赋值函数将此对象赋值给一个引用时,需要增加此对象的引用计数。还有就是,当一个引用变量的生命周期结束时,需要更新此对象的引用计数器。

由于引用计数无法解决相互引用的情况,所以该算法并没有被任何jvm采用。

2.标记-清除收集器

收集过程分为2个阶段
1. 首先停止所有工作,从根集遍历所有被引用的节点,然后进行标记,最后恢复所有工作
2. 收集阶段会收集那些没有被标记的节点,然后返回空闲链表

标记-清除法的缺点在于
1.标记阶段暂停的时间可能很长,而整个堆在交换阶段又是可访问的,可能会导致被换页换出内存。
2.另外一个问题在于,不管你这个对象是不是可达的,即是不是垃圾,都要在清楚阶段被检查一遍,非常耗时.3,标记清楚这两个动作会产生大量的内存碎片,于是当有大对象进行分配时,不需要触发一次垃圾回收动作

3.拷贝收集器(Copying Collectors)(适用于young generation:PSYoungGen)

该算法的提出是为了克服句柄的开销和解决堆碎片的垃圾回收。
    将内存分为两个区域(from space和to space)。所有的对象分配内存都分配到from space。在清理非活动对象阶段,把所有标志为活动的对象,copy到to space,之后清楚from space空间。然后互换from sapce和to space的身份。既原先的from space变成to sapce,原先的to space变成from space。每次清理,重复上述过程。

现在的商业虚拟机都用这种算法来回收新生代,因为新生代的大多数的生命周期都很短暂,所以前面提到的两块相互切换的区域并不需要按照1:1来进行分配。而是分配了一个Eden区,两个Survivor区。大部分对象默认的都是在 Eden区中生成。当垃圾回收时,Eden和其中的一个Survivor区的存活对象将被复制到另外一个Survivor区,当另外一个Survivor区也满了的时候,从Eden和第一个Survivor区复制过来的并且此时还存活的对象,将被复制到tenured generation。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。
    young generation的gc称为minor gc。经过数次minor gc,依旧存活的对象,将被移出young generation,移到tenured generation

优点:copy算法不理会非活动对象,copy数量仅仅取决为活动对象的数量。并且在copy的同时,整理了heap空间,即,to space的空间使用始终是连续的,内存使用效率得到提高。
缺点:默认情况下Eden:Survivor=8:1, 所以总会有100-(80+10)%的新生代内存会被浪费掉。

4.标记-整理收集器(Mark-Compact Collectors)(适用于存放生命周期较长对象的tenured generation:PSOldGen)

标记整理收集器,通过融合了标记-清除收集器和拷贝收集器的优点,很好的解决了拷贝收集策略中,堆内存浪费严重的问题。

标记整理收集器分为2个阶段
1. 标记阶段, 这个阶段和标记-清除收集器的标记阶段相同
2. 整理阶段, 这个阶段将所有做了标记的活动对象整理到堆的底部(有点像是磁盘碎片整理,呵呵)

生命周期较长的对象,归入到tenured generation。一般是经过多次minor gc,还依旧存活的对象,将移入到tenured generation。(当然,在minor gc中如果存活的对象的超过survivor的容量,放不下的对象会直接移入到tenured generation)tenured generation的gc称为major gc,就是通常说的full gc。由于tenured generaion区域比较大,而且通常对象生命周期都比较长,所以这部分的gc时间比较长。
    minor gc可能引发full gc。当eden+from space的空间大于tenured generation区的剩余空间时,会引发full gc。这是悲观算法,要确保eden+from space的对象如果都存活,必须有足够的tenured generation空间存放这些对象。

三、其它gc补充

商业jvm普遍使用这个方法来判断对象是否可达:通过类的静态变量及栈中变量依次遍历可及的为存货对象。

finalize()方法:这个方法会在gc时被调用。但是gc并不保证什么时候销毁对象,即使调用System.gc()方法,也只是通知它进行回收,jvm并不保证立刻执行它。有时候如果在这个方法里写入不恰当的代码引用了一些对象可能会导致gc永远不会回收对象,因此不推荐在这里进行流关闭之类c++析构函数干的工作。

时间: 2024-10-09 23:48:05

GC heap 简述的相关文章

Java Hotspot G1 GC的一些关键技术

G1 GC,全称Garbage-First Garbage Collector,通过-XX:+UseG1GC参数来启用,作为体验版随着JDK 6u14版本面世,在JDK 7u4版本发行时被正式推出,相信熟悉JVM的同学们都不会对它感到陌生.在JDK 9中,G1被提议设置为默认垃圾收集器(JEP 248).在官网中,是这样描述G1的: The Garbage-First (G1) collector is a server-style garbage collector, targeted for

Advanced .NET Debugging: Managed Heap and Garbage Collection(转载,托管堆查内存碎片问题解决思路)

原文地址:http://www.informit.com/articles/article.aspx?p=1409801&seqNum=4 Debugging Managed Heap Fragmentation Earlier in the chapter, we described a phenomenon known as heap fragmentation, in which free and busy blocks are arranged and interleaved on th

Windbg Extension NetExt 使用指南 【3】 ---- 挖掘你想要的数据 Managed Heap

摘要 : NetExt中有两个比较常用的命令可以用来分析heap上面的对象. 一个是!wheap, 另外一个是!windex. !wheap 这个命令可以用于打印出heap structure信息. heap 上 object汇总后的信息. 这个命令也可以按照一些条件过滤出objects, 不过执行速度比较慢. 在这一点上, 更推荐!windex.!windex是一个非常常用的命令. 这个命令可以用来查找heap上面实现某个interface, 继承某个abstract class 或者clas

jvm的内存分布,参数配置 和 GC处理机制

转载 url: http://blog.csdn.net/ning109314/article/details/10411495 url:http://www.cnblogs.com/sunada2005/p/3577799.html url:http://www.open-open.com/lib/view/open1437834571349.html url:http://www.cnblogs.com/redcreen/archive/2011/05/04/2037056.html url

ART运行时Foreground GC和Background GC切换过程分析

通过前面一系列文章的学习,我们知道了ART运行时既支持Mark-Sweep GC,又支持Compacting GC.其中,Mark-Sweep GC执行效率更高,但是存在内存碎片问题:而Compacting GC执行效率较低,但是不存在内存碎片问题.ART运行时通过引入Foreground GC和Background GC的概念来对这两种GC进行扬长避短.本文就详细分析它们的执行过程以及切换过程. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 在前面AR

ART运行时垃圾收集(GC)过程分析

ART运行时与Dalvik虚拟机一样,都使用了Mark-Sweep算法进行垃圾回收,因此它们的垃圾回收流程在总体上是一致的.但是ART运行时对堆的划分更加细致,因而在此基础上实现了更多样的回收策略.不同的策略有不同的回收力度,力度越大的回收策略,每次回收的内存就越多,并且它们都有各自的使用情景.这样就可以使得每次执行GC时,可以最大限度地减少应用程序停顿.本文就详细分析ART运行时的垃圾收集过程. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! ART运行

ART运行时Compacting GC为新创建对象分配内存的过程分析

在引进Compacting GC后,ART运行时优化了堆内存分配过程.最显著特点是为每个ART运行时线程增加局部分配缓冲区(Thead Local Allocation Buffer)和在OOM前进行一次同构空间压缩(Homogeneous Space Compact).前者可提高堆内存分配效率,后者可解决内存碎片问题.本文就对ART运行时引进Compacting GC后的堆内存分配过程进行分析. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 从接口层面

ART运行时Compacting GC堆创建过程分析

引进了Compacting GC之后,ART运行时的堆空间结构就发生了变化.这是由于Compacting GC和Mark-Sweep GC的算法不同,要求底层的堆具有不同的空间结构.同时,即使是原来的Mark-Sweep GC,由于需要支持新的同构空间压缩特性(Homogeneous Space Compact),也使得它们要具有与原来不一样的堆空间结构.本文就对这些堆空间创建过程进行详细的分析. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 从前面AR

使用PerfView诊断.Net GC的问题

PerfView 概述: PerfView是一个可以帮助你分析CPU和内存问题的工具软件.它非常轻量级也不会入侵诊断的程序,在诊断过程中对诊断的程序影响甚微. Visual Studio自带的性能分析功能在CPU占用.时间消耗.内存分配等方面的诊断效果还算不错,但PerfView可以提供更加丰富的诊断分析信息. 在这篇文章中,我将使用PerfView给你展现如下功能: GC回收发生的频率以及回收所消耗的时间: 获取导致Large object分配的原因: 内存被谁占用了: 对比哪个托管对象增大的