原文地址:http://www.importnew.com/1993.html
注:我只转了这篇文章的前一部分,后一部分的关于几种GC方式的解释,感觉不是很清晰。
对于Java开发人员来说,了解垃圾回收机制(GC)有哪些好处呢?首先可以满足作为一名软件工程师的求知欲,其次,深入了解GC如何工作可以帮你写出更好的Java应用。
这仅仅代表我个人的意见,但我坚信一个精通GC的人往往是一个好的Java开发者。如果你对GC的处理过程感兴趣,说明你已经具备较大规模应用的开发经验。如果你曾经想过如何正确的选择GC算法,那意味着你已经完全理解你所开发的应用的特点。当然,我们不能以偏概全,这不能作为评价一个好的开发人员的共通标准。但是,我要说的是,深入理解GC是成为一名伟大的程序员的必经之路。
这是成为JavaGC专家系列文章的第一篇,本篇主要针对GC机制进行介绍,在下一篇中,我们将重点探讨分析GC状态以及来自NHN的GC调优的例子。
本文的目的是以一种简单的方式向你介绍GC机制。我希望这些文章能够帮到你。实际上,我的学生已经在Twitter上发布了一些很好的关于Java内核的文章,并且大受欢迎。有兴趣的话,你也可以关注他们。
回到正题,咱们继续谈垃圾回收,在学习GC之前,你首先应该记住一个单词:“stop-the-world”。Stop-the-world会在任何一种GC算法中发生。Stop-the-world意味着 JVM 因为要执行GC而停止了应用程序的执行。当Stop-the-world发生时,除了GC所需的线程以外,所有线程都处于等待状态,直到GC任务完成。GC优化很多时候就是指减少Stop-the-world发生的时间。
按代的垃圾回收机制
在Java程序中不能显式地分配和注销内存。有些人把相关的对象设置为null或者调用System.gc()来试图显式地清理内存。设置为null至少没什么坏处,但是调用System.gc()会显著地影响系统性能,必须彻底杜绝(还好,我还没有见到NHN的哪个开发者调用这个方法)。
在Java中,开发人员无法直接在程序代码中清理内存,而是由垃圾回收器自动寻找不必要的垃圾对象,并且清理掉他们。垃圾回收器会在下面两种假设(hypotheses)成立的情况下被创建(称之为假设不如改为推测(suppositions)或者前提(preconditions))。
- 大多数对象会很快变得不可达
- 只有很少的由老对象(创建时间较长的对象)指向新生对象的引用
这些假设我们称之为弱年代假设( weak generational hypothesis)。为了强化这一假设,HotSpot虚拟机将其物理上划分为两个–新生代(young generation)和老年代(old generation)。
新生代(Young generation): 绝大多数最新被创建的对象会被分配到这里,由于大部分对象在创建后会很快变得不可到达,所以很多对象被创建在新生代,然后消失。对象从这个区域消失的过程我们称之为”minor GC“。
老年代(Old generation): 对象没有变得不可达,并且从新生代中存活下来,会被拷贝到这里。其所占用的空间要比新生代多。也正由于其相对较大的空间,发生在老年代上的GC要比新生代少得多。对象从老年代中消失的过程,我们称之为”major GC“(或者”full GC“)
请看下面这个图表。
图1 : GC 空间 & 数据流
上图中的持久代( permanent generation )也被称为方法区(method area)。他用来保存类常量以及字符串常量。因此,这个区域不是用来永久的存储那些从老年代存活下来的对象。这个区域也可能发生GC。并且发生在这个区域上的GC事件也会被算为major GC。
有些人可能会问:
如果老年代的对象需要引用一个新生代的对象,会发生什么呢?
为了解决这个问题,老年代中存在一个”card table“,他是一个512 byte大小的块。所有老年代的对象指向新生代对象的引用都会被记录在这个表中。当针对新生代执行GC的时候,只需要查询card table来决定是否可以被收集,而不用查询整个老年代。这个card table由一个write barrier来管理。write barrier给GC带来了很大的性能提升,虽然由此可能带来一些开销,但GC的整体时间被显著的减少。
图 2: Card Table 结构
新生代的构成
为了更好地理解GC,我们现在来学习新生代,新生代是用来保存那些第一次被创建的对象,他可以被分为三个空间
- 一个伊甸园空间(Eden )
- 两个幸存者空间(Survivor )
一共有三个空间,其中包含两个幸存者空间。每个空间的执行顺序如下:
- 绝大多数刚刚被创建的对象会存放在伊甸园空间。
- 在伊甸园空间执行了第一次GC之后,存活的对象被移动到其中一个幸存者空间。
- 此后,在伊甸园空间执行GC之后,存活的对象会被堆积在同一个幸存者空间。
- 当一个幸存者空间饱和,还在存活的对象会被移动到另一个幸存者空间。之后会清空已经饱和的那个幸存者空间。
- 在以上的步骤中重复几次依然存活的对象,就会被移动到老年代。
如果你仔细观察这些步骤就会发现,其中一个幸存者空间必须保持是空的。如果两个幸存者空间都有数据,或者两个空间都是空的,那一定标志着你的系统出现了某种错误。
通过频繁的minor GC将数据移动到老年代的过程可以用下图来描述:
图 3: GC执行前后对比
需要注意的是HotSpot虚拟机使用了两种技术来加快内存分配。他们分别是是”bump-the-pointer“和“TLABs(Thread-Local Allocation Buffers)”。
Bump-the-pointer技术跟踪在伊甸园空间创建的最后一个对象。这个对象会被放在伊甸园空间的顶部。如果之后再需要创建对象,只需要检查伊甸园空间是否有足够的剩余空间。如果有足够的空间,对象就会被创建在伊甸园空间,并且被放置在顶部。这样以来,每次创建新的对象时,只需要检查最后被创建的对象。这将极大地加快内存分配速度。但是,如果我们在多线程的情况下,事情将截然不同。如果想要以线程安全的方式以多线程在伊甸园空间存储对象,不可避免的需要加锁,而这将极大地的影响性能。TLABs 是HotSpot虚拟机针对这一问题的解决方案。该方案为每一个线程在伊甸园空间分配一块独享的空间,这样每个线程只访问他们自己的TLAB空间,再与bump-the-pointer技术结合可以在不加锁的情况下分配内存。
以上是针对新生代空间GC技术的简要介绍,你不需要刻意记住我刚刚提到的两种技术。不知道他们不会对你产生什么影响,但是请务必记住在对象刚刚被创建之后,是保存在伊甸园空间的。那些长期存活的对象会经由幸存者空间转存在老年代空间。
相关推荐
在第一篇文章成为JavaGC专家PartI—深入浅出Java垃圾回收机制中我们学习了不同GC算法的执行过程,GC如何工作,新生代及老年代的基本概念,在JDK7中你应该了解的5种GC类型以及他们的性能如何。在第二篇文章成为JavaGC...
深入浅出Java Swing程序设计,含源码。共四部分,这是第一部分。
Java垃圾回收(Garbage Collection, 简称GC)是Java平台中的一项重要特性,它自动管理内存,释放不再使用的对象,避免了程序员手动管理内存可能导致的内存泄露问题。本篇将深入探讨Java垃圾回收的精华部分,以及在...
head first java中文版 第二版 扫描版 共4个分卷,因为我的上传权限限制了. 如果下载后解压搜有问题,可以发邮件给我21305@163.com.
深入浅出Java_Swing程序设计(高清),第二部分,分卷压缩 Swing开发入门经典教材
《深入浅出jBPM》深入浅出,示例丰富,实用性强,适合有一定Java基础的读者阅读。
深入浅出Java Swing程序设计,含源码。共四部分,这是第四部分。
深入浅出Java Swing程序设计,含源码。共四部分,这是第二部分。
深入浅出Java Swing程序设计,含源码。共四部分,这是第三部分。
深入浅出 Java Swing 程序设计(高清)。第一部分,分卷压缩。 Swing开发经典教材!
深入浅出西门子WinCC V6.0(第2版).part5
深入浅出设计模式(Head First Design Patterns)完整版,由本人精心整理网上的JPG版制作成PDF版供各位编程爱好者下载学习, 这部模式教程诙谐幽默,寓教于乐,实乃菜鸟成才必备之选。共分为11个压缩包,绝对的物有所...
深入浅出Java Swing程序设计.part1.rar 大小31.7 MB (此书分两份上传)
深入浅出Java Swing程序设计.part2.rar 大小31.7 MB (此书分两份上传)
深入浅出Servlets and JSP第二版.part2
深入浅出设计模式(Head First Design Patterns)完整版,由本人精心整理网上的JPG版制作成PDF版供各位编程爱好者下载学习, 这部模式教程诙谐幽默,寓教于乐,实乃菜鸟成才必备之选。共分为11个压缩包,绝对的物有所...
深入浅出设计模式(Head First Design Patterns)完整版,由本人精心整理网上的JPG版制作成PDF版供各位编程爱好者下载学习,这部模式教程诙谐幽默,寓教于乐,实乃菜鸟成才必备之选。共分为11个压缩包,绝对的物有所值...
深入浅出EXTJS第2版.pdf part2(共三部分) 纯正PDF版,非扫描版本。在某论坛下,希望对大家学习有帮助。
深入浅出西门子WinCC V6.0(第2版).part2