一、基本回收算法

1. 引用计数(Reference Counting)

比较古老的回收算法。原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为0的对象。此算法最致命的是无法处理循环引用的问题。

2. 标记-清除(Mark-Sweep)

此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。此算法需要暂停整个应用,同时,会产生内存碎片。

3. 复制(Copying)

此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。次算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不过出现“碎片”问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间。

4. 标记-整理(Mark-Compact)

此算法结合了 “标记-清除”和“复制”两个算法的好处。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象 “压缩”到堆的其中一块,按顺序排放。此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。

5. 增量收集(Incremental Collecting)

实施垃圾回收算法,即:在应用进行的同时进行垃圾回收。不知道什么原因JDK5.0中的收集器没有使用这种算法的。

6. 分代(Generational Collecting)

使用对对象生命周期分析后得出的垃圾回收算法。把对象分为年青代、年老代、持久代,对不同生命周期的对象使用不同的算法(上述方式中的一个)进行回收。现在的垃圾回收器(从J2SE1.2开始)都是使用此算法的。

1. Young(年轻代)

年轻代分三个区。一个Eden区,两个 Survivor区。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个 Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要注重,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。

2. Tenured(年老代)

年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。

3. Perm(持久代)

用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中增加的类。持久代大小通过-XX:MaxPermSize=进行设置。

二、GC类型GC有两种类型:Scavenge GC和Full GC。

1. Scavenge GC

一般情况下,当新版对象生成,并且在Eden申请空间失败时,就好触发Scavenge GC,堆Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。

2. Full GC

对整个堆进行整理,包括Young、Tenured和Perm。Full GC比Scavenge GC要慢,因此应该尽可能减少Full GC。有如下原因可能导致Full GC:

* Tenured被写满

* Perm域被写满

* System.gc()被显示调用

* 上一次GC之后Heap的各域分配策略动态变化

分代垃圾回收过程演示

1.

2.

3.

4.

二、垃圾回收器

目前的收集器主要有三种:串行收集器、并行收集器、并发收集器。

1. 串行收集器

使用单线程处理所有垃圾回收工作,因为无需多线程交互,所以效率比较高。但是,也无法使用多处理器的优势,所以此收集器适合单处理器机器。当然,此收集器也可以用在小数据量(100M左右)情况下的多处理器机器上。可以使用-XX:+UseSerialGC打开。

2. 并行收集器

1. 对年轻代进行并行垃圾回收,因此可以减少垃圾回收时间。一般在多线程多处理器机器上使用。使用-XX:+UseParallelGC.打开。并行收集器在J2SE5.0第六6升级上引入,在Java SE6.0中进行了增强--可以堆年老代进行并行收集。如果年老代不使用并发收集的话,是使用单线程进行垃圾回收,因此会制约扩展能力。使用-XX:+UseParallelOldGC打开。

2. 使用-XX:ParallelGCThreads=设置并行垃圾回收的线程数。此值可以设置与机器处理器数量相等。

3. 此收集器可以进行如下配置:

* 最大垃圾回收暂停:指定垃圾回收时的最长暂停时间,通过-XX:MaxGCPauseMillis=指定。为毫秒.如果指定了此值的话,堆大小和垃圾回收相关参数会进行调整以达到指定值。设定此值可能会减少应用的吞吐量。

* 吞吐量:吞吐量为垃圾回收时间与非垃圾回收时间的比值,通过-XX:GCTimeRatio=来设定,公式为1/(1+N)。例如,-XX:GCTimeRatio=19时,表示5%的时间用于垃圾回收。默认情况为99,即1%的时间用于垃圾回收。

3. 并发收集器

可以确保大部分工作都并发进行(应用不停止),垃圾回收只暂停很少的时间,此收集器适合对响应时间要求比较高的中、大规模应用。使用-XX:+UseConcMarkSweepGC打开。

1. 并发收集器主要减少年老代的暂停时间,他在应用不停止的情况下使用独立的垃圾回收线程,跟踪可达对象。在每个年老代垃圾回收周期中,在收集初期并发收集器会对整个应用进行简短的暂停,在收集中还会再暂停一次。第二次暂停会比第一次稍长,在此过程中多个线程同时进行垃圾回收工作。

2. 并发收集器使用处理器换来短暂的停顿时间。在一个N个处理器的系统上,并发收集部分使用K/N个可用使用的处理器进行回收,一般情况下1<=K<=N/4。

3. 在只有一个处理器的主机上使用并发收集器,设置为incremental mode项目也可获得较短的停顿时间。

4. 浮动垃圾:由于在应用运行的同时进行垃圾回收,所以有些垃圾可能在垃圾回收进行完成时产生,这样就造成了“Floating Garbage”,这些垃圾需要在下次垃圾回收周期时才能回收掉。所以,并发收集器一般需要20%的预留空间用于这些浮动垃圾。

5. Concurrent Mode Failure:并发收集器在应用运行时进行收集,所以需要确保堆在垃圾回收的这段时间有足够的空间供程序使用,否则,垃圾回收还未完成,堆空间先满了。这种情况下将会发生“并发项目失败”,此时整个应用将会暂停,进行垃圾回收。

6. 启动并发收集器:因为并发收集在应用运行时进行收集,所以必须确保收集完成之前有足够的内存空间供程序使用,否则会出现“Concurrent Mode Failure”。通过设置-XX:CMSInitiatingOccupancyFraction=指定还有多少剩余堆时开始执行并发收集

4. 小结

* 串行处理器:

--适用情况:数据量比较小(100M左右);单处理器下并且对响应时间无要求的应用。

--缺点:只能用于小型应用

* 并行处理器:

--适用情况:“对吞吐量有高要求”,多CPU、对应用响应时间无要求的中、大型应用。举例:后台处理、科学计算。

--缺点:应用响应时间可能较长

* 并发处理器:

--适用情况:“对响应时间有高要求”,多CPU、对应用响应时间有较高要求的中、大型应用。举例:Web服务器/应用服务器、电信交换、集成开发环境。

三、GC基本原理GC(Garbage Collection),是JAVA/.NET中的垃圾收集器。

Java是由C++发展来的,它摈弃了C++中一些繁琐容易出错的东西,引入了计数器的概念,其中有一条就是这个GC机制(C#借鉴了JAVA)

编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。所以,Java的内存管理实际上就是对象的管理,其中包括对象的分配和释放。

对于程序员来说,分配对象使用new关键字;释放对象时,只要将对象所有引用赋值为null,让程序不能够再访问到这个对象,我们称该对象为"不可达的".GC将负责回收所有"不可达"对象的内存空间。

对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC使用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的".当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。但是,为了确保 GC能够在不同系统实现的问题,Java规范对GC的很多行为都没有进行严格的规定。例如,对于使用什么类型的回收算法、什么时候进行回收等重点问题都没有明确的规定。因此,不同的JVM的实现者往往有不同的实现算法。这也给Java程序员的开发带来行多不确定性。本文研究了几个与GC工作相关的问题,努力减少这种不确定性给Java程序带来的负面影响。

四、GC分代划分JVM内存模型中Heap区分两大块,一块是 Young Generation,另一块是Old Generation

1) 在Young Generation中,有一个叫Eden Space的空间,主要是用来存放新版生的对象,还有两个Survivor Spaces(from、to),它们的大小总是一样,它们用来存放每次垃圾回收后存活下来的对象。

2) 在Old Generation中,主要存放应用程序中生命周期长的内存对象。

3) 在Young Generation块中,垃圾回收一般用Copying的算法,速度快。每次GC的时候,存活下来的对象首先由Eden拷贝到某个SurvivorSpace,当Survivor Space空间满了后,剩下的live对象就被直接拷贝到OldGeneration中去。因此,每次GC后,Eden内存块会被清空。

4) 在Old Generation块中,垃圾回收一般用mark-compact的算法,速度慢些,但减少内存要求。

5) 垃圾回收分多级,0级为全部(Full)的垃圾回收,会回收OLD段中的垃圾;1级或以上为部分垃圾回收,只会回收Young中的垃圾,内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新版的Java对象的情况。

五、增量式GC增量式GC(Incremental GC),是GC在JVM中通常是由一个或一组进程来实现的,它本身也和用户程序一样占用heap空间,运行时也占用CPU。

当GC进程运行时,应用程序停止运行。因此,当GC运行时间较长时,用户能够感到Java程序的停顿,另外一方面,如果GC运行时间太短,则可能对象回收率太低,这意味着还有很多应该回收的对象没有被回收,仍然占用大量内存。因此,在设计GC的时候,就必须在停顿时间和回收率之间进行权衡。一个好的GC实现允许用户定义自己所需要的设置,例如有些内存有限的设备,对内存的使用量非常敏感,希望GC能够准确的回收内存,它并不在意程序速度的快慢。另外一些实时网游,就不能够允许程序有长时间的中断。

增量式GC就是通过一定的回收算法,把一个长时间的中断,划分为很多个小的中断,通过这种方式减少GC对用户程序的影响。虽然,增量式GC在整体性能上可能不如普通GC的效率高,但是它能够减少程序的最长停顿时间。

Sun JDK提供的HotSpot JVM就能支持增量式GC。HotSpot JVM缺省GC方式为不使用增量GC,为了启动增量GC,我们必须在运行Java程序时增加-Xincgc的参数。

HotSpot JVM增量式GC的实现是使用Train GC算法,它的基本想法就是:将堆中的所有对象按照创建和使用情况进行分组(分层),将使用频繁高和具有相关性的对象放在一队中,随着程序的运行,不断对组进行调整。当GC运行时,它总是先回收最老的(最近很少访问的)的对象,如果整组都为可回收对象,GC将整组回收。这样,每次GC运行只回收一定比例的不可达对象,确保程序的顺畅运行。

JAVA垃圾回收器源码_浅谈关于Java的GC垃圾回收器的一些基本概念相关推荐

  1. java五子棋网络版源码_网络版五子棋的java源代码.pdf

    网络版五子棋的java源代码.pdf 还剩 44页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,很抱歉,此页已超出免费预览范围啦! 如果喜欢就下载吧,价低环保! 内容要点: *更改姓名Pa ...

  2. java swing游戏源码-宇宙战争游戏,Java飞船射击游戏

    原文:java swing游戏源码-宇宙战争游戏,Java飞船射击游戏 源代码下载地址: http://www.zuidaima.com/share/1880717151603712.htm 一个基于 ...

  3. 中文文本校对源码java_浅谈中文文本自动纠错在影视剧搜索中应用与Java实现

    1.背景: 这周由于项目需要对搜索框中输入的错误影片名进行校正处理,以提升搜索命中率和用户体验,研究了一下中文文本自动纠错(专业点讲是校对,proofread),并初步实现了该功能,特此记录. 2.简 ...

  4. java方法区对象类型_浅谈Java内存区域与对象创建过程

    一.java内存区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区域则 ...

  5. java招投标网站源码_基于jsp的招标系统-JavaEE实现招标系统 - java项目源码

    基于jsp+servlet+pojo+mysql实现一个javaee/javaweb的招标系统, 该项目可用各类java课程设计大作业中, 招标系统的系统架构分为前后台两部分, 最终实现在线上进行招标 ...

  6. java 上传源码_和付费网盘说再见,跟着本文自己起个网盘(Java)

    项目源码获取:关注转发之后私信回复[源码]即可免费获取到 一.项目介绍 一款开源.使用简单.功能完整的 Java 网盘/云盘系统.支持在线视频播放.文档在线预览.音乐播放.图片查看等功能的文件云存储平 ...

  7. java和python混合编程_浅谈C++与Java混合编程

    在学习编程的过程中, 我觉得不止要获得课本的知识, 更多的是通过学习技术知识提高解决问题的能力, 这样我们才能走在最前方, 更 多 Java 学习,请登陆疯狂 java 官网. 现实的情况是, 真实的 ...

  8. java婚庆网站源码_基于jsp的婚庆网站-JavaEE实现婚庆网站 - java项目源码

    基于jsp+servlet+pojo+mysql实现一个javaee/javaweb的婚庆网站, 该项目可用各类java课程设计大作业中, 婚庆网站的系统架构分为前后台两部分, 最终实现在线上进行婚庆 ...

  9. java 并发框架源码_某网Java并发编程高阶技术-高性能并发框架源码解析与实战(云盘下载)...

    第1章 课程介绍(Java并发编程进阶课程) 什么是Disruptor?它一个高性能的异步处理框架,号称"单线程每秒可处理600W个订单"的神器,本课程目标:彻底精通一个如此优秀的 ...

最新文章

  1. Chrome Restful Api 测试工具 Postman-REST-Client离线安装包下载,Axure RP Extension for Chrome离线版下载...
  2. C#数组排序(按列)
  3. Bresenham 生成直线
  4. TP5 上传文件 中文乱码问题
  5. baidumap vue 判断范围_vue中百度地图API的调用
  6. PyCharm中的Debug使用
  7. 计算机会计u8实验报告,会计信息系统实验报告 用友u8
  8. 直流电机正反转驱动电路板
  9. 用python对图片进行反色处理
  10. 六自由度机械臂运动学分析及其轨迹规划
  11. 安卓如何调出软键盘_Android软键盘-显示隐藏软键盘
  12. 从0到1智能风控决策引擎构建
  13. NBA赛事直播超清画质背后:阿里云视频云「窄带高清2.0」技术深度解读
  14. 微型计算机中i 0设备的含义,i/0设备的含义是什么
  15. 浏览器代理服务的另一选择——pac配置
  16. 利用C++调用PyTorch的模型
  17. 如何解除计算机上的安全警报,windows安全警报怎么关闭 为什么总是弹出安全警告...
  18. 基于51单片机的电子温度计系统的设计与实现
  19. 健康管理的营利模式及体系构建
  20. 基于Python实现点菜系统

热门文章

  1. 2019/2/17 Python今日收获
  2. Java学习笔记_180704_final和static关键字
  3. 机器学习 - 支持向量机
  4. [BZOJ]1055: [HAOI2008]玩具取名
  5. Replication的犄角旮旯(二)--寻找订阅端丢失的记录
  6. 应用高斯分布来解决异常检测问题(一)
  7. 全球首发!惯性导航导论(剑桥大学)第四部分
  8. NLP大魔王 · BERT 全解读
  9. 手把手!基于领域预训练和对比学习SimCSE的语义检索(附源码)
  10. shell waite php,linux shell wait命令详解