GC,先给一个定义:
当一个电脑上的动态内存不再需要时,就应该予以释放,以让出内存,这种内存资源管理,称为垃圾回收(garbage collection)
实际上,为了保证gc能够在不同的平台得以实现,java规范本身并没有对gc的具体行为做约束,比如什么时候gc,采用什么算法gc等等…下边,我们先来看看一些常用或者曾经常用的gc算法。
什么时候GC
- 引用计数
引用计数存储对特定对象的所有引用数,也就是说,当应用程序创建引用以及引用超出范围时,jvm必须适当增减引用数。当某对象的引用数为0时,便可以进行垃圾收集。
- 对象引用遍历
早期的jvm使用引用计数,现在大多数jvm采用对象引用遍历。对象引用遍历从一组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。在对象遍历阶段,gc必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标记(marking)对象。 然后,gc要删除不可到达的对象。删除时,有些gc只是简单的扫描堆栈,删除未标记的对象,并释放它们的内存以生成新的对象,这叫做清除(sweeping)。这种方法的问题在于内存会分成好多小段,而它们不足以用于新的对象,但是组合起来却很大。因此,许多gc可以重新组织内存中的对象,并进行压缩(compact),形成可利用的空间。 为此,gc需要停止其他的活动活动。这种方法意味着所有与应用程序相关的工作停止,只有gc运行。结果,在响应期间增减了许多混杂请求。另外,更复杂的 gc不断增加或同时运行以减少或者清除应用程序的中断。有的gc使用单线程完成这项工作,有的则采用多线程以增加效率。
GC算法
- 标记-清除算法
这种算法首先遍历对象图并标记可到达的对象,然后扫描堆栈以寻找未标记对象并释放它们的内存。这种算法一般使用单线程工作并停止其他操作。
- 标记-压缩算法
- 有时也叫标记-清除-压缩算法,与标记-清除算法有相同的标记阶段。在第二阶段,则把标记对象复制到堆栈的新域中以便压缩堆栈。这种收集器也停止其他操作。
- 复制算法
这种收算法将堆栈分为两个域,常称为半空间。每次仅使用一半的空间,jvm生成的新对象则放在另一半空间中。gc运行时,它把可到达对象复制到另一半空间,从而压缩了堆栈。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。
- 增量算法
增量算法把堆栈分为多个域,每次仅从一个域收集垃圾。这会造成较小的应用程序中断。
- 分代算法
这种算法把堆栈分为两个或多个域,用以存放不同寿命的对象。jvm生成的新对象一般放在其中的某个域中。过一段时间,继续存在的对象将获得使用期并转入更长寿命的域中。分代算法对不同的域使用不同的算法以优化性能。
- 并发算法
并发算法与应用程序同时运行。这些算法在某点上(比如压缩时)一般都不得不停止其他操作以完成特定的任务,但是因为其他应用程序可进行其他的后台操作,所以中断其他处理的实际时间大大降低。
- 并行算法
并行算法使用某种传统的算法并使用多线程并行的执行它们的工作。在多cpu机器上使用多线程技术可以显著的提高java应用程序的可扩展性。
GC流程
了解GC流程,就要先了解jvm的堆内存结构
- Young:
- Eden:存放新生对象。
- From:存放经过垃圾回收没有被清除的对象。
- To:和From做Copying collection,位置会和From互换。
- Tenured Space:新域中的对象,经过了一定次数的GC循环后,被移入旧域。
- Permanent Space: 存储类和方法对象,从配置的角度看,这个域是独立的,不包括在JVM堆内。
在sun 的文档说明中,对JVM堆的新域,是采用coping算法(复制算法),该算法的提出是为了克服句柄的开销和解决堆碎片的垃圾回收。它开始时把堆分成一个对象面和多个空闲面,程序从对象面为对象分配空间,当对象满了,基于 coping算法的垃圾收集就从根集中扫描活动对象,并将每个活动对象复制到空闲面(使得活动对象所占的内存之间没有空闲洞),这样空闲面变成了对象面,原来的对象面变成了空闲面,程序会在新的对象面中分配内存。
好,现在我们来看一下gc的流程:
1. 对于新生成的对象,都放在Eden中;当Eden充满时,GC将开始工作,即所谓的Young GC,首先停止应用程序的运行,开始收集垃圾。
-
- 这时,会把所有可以找到的对象放到From Space
- 一旦From Space充满,GC会把From中可以找到的对象放到To Space
- 一旦To Space充满,GC会把To中可以找到的对象放到From Space,并覆盖From中原有的储存对象
- 如此交替,经过一定次数的GC操作之后,会把仍然可以找到的对象放到Tenured Space
2. 当Tenured Space(旧域)满了,便会触发一次Full GC,Full GC很消耗内存,把old,young里面大部分垃圾回收掉。这个时候用户线程都会被block。
另外,在整个过程中,有两个地方值得我们注意:
1. 对象在新域中,采用的是coping(复制)算法
原因就是大部分新生对象都是短期存在的。
前边说过,复制算法适合短生存期对象。最理想的状态是,所有移出Eden、From或者To的对象都会被收集,这样可以使要复制的对象量达到最小。如果持续复制长期存在的对象…岂不是搬来搬去瞎倒腾。
2. 对于旧域,则采用的是标记-清除-压缩算法
前边说过,Full GC很耗内存,且会block住用户进程。压缩,虽是一个耗时操作,但为了提高旧域的利用率,减少Full GC次数,是必要的。
引用:http://ningq.com/2010/11/talk-about-java-gc.html
oracle官方介绍:http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/G1GettingStarted/index.html
相关推荐
GC java 手册 kindle格式 GC java 手册 kindle格式 GC java 手册 kindle格式
让你对java gc 的工作原理有更深的了解 谢谢下载
NULL 博文链接:https://wangwengcn.iteye.com/blog/1606192
GChisto及CMS GC相应补丁文件,补丁文件未亲测。 This patch adds the following features and improvements when using CMS GC in incremental mode: detecting Full GCs corrected parsing errors when using -XX:...
Java基础[Java基础]--Java GC工作原理
Java GC与性能调优文档 作者:高飞
GCViewer 能否分析 java 程序 GC 日志,能否图表展示堆内存,年轻代,老年代,永久带以及full gc 的使用情况
成为JavaGC专家PartII—如何监控Java垃圾回收机制Java开发Java经验技巧共12页.pdf.zip
java查看哪个进程频繁GC垃圾回收
Java VisualVM GC插件
JVM内存管理的介绍,编写GC友好的代码。 本材料主要关心 Sun Hotspot JVM 6的内存管理 Sun Hotspot JVM 6的GC模型 主要针对JVM6的GC模型,但也会简单介绍Java 7的G1 编写GC友好代码的一些技巧
Java SE编程入门教程 java GC(共6页).pptx Java SE编程入门教程 java instanceof(共3页).pptx Java SE编程入门教程 java IO(共28页).pptx Java SE编程入门教程 java Math(共11页).pptx Java SE编程入门教程 ...
jvm配置参数详解,以及Java gc详解
java7 GC 参数配置说明文档,详细介绍了每个参数的作用
NULL 博文链接:https://4ujava.iteye.com/blog/553867
GC有两种类型:Scavenge GC(也称Young GC)和Full GC。 一般Full GC时,机器的Load会升高,应用也会停止响应一会(持续长达几秒),如果应用一直频繁的进行FullGC,一方面会出现应用无法提供正常服务,另一方面...
NULL 博文链接:https://seanzhou.iteye.com/blog/2003941
面向GC的Java编程Java开发Java经验技巧共7页.pdf.zip
Java GC的副本.pptx