`
solidsnake2007
  • 浏览: 29810 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Java中的GC算法--sun早期GC算法

 
阅读更多

        说到Java的GC大家应该都很熟悉,但随着JVM种类的不断增加,以及日益成熟的项目实践,使得GC(垃圾回收)技术经过了一代又一代的变迁。下面,我想要为大家描述一种现在使用最多的JVM GC算法----代分算法---的七大姑八大姨夫们。

 

        在正式开始之前,想和大家扯扯GC的历史问题,这样可以使大家有一个稍微完整一些的概念。

 

    时间轴 :

        在Java出现之前,存在着一种伟大的语言,它的名字叫做C。C是Basic的亲儿子,它的爸爸教会了它各种技能。由于它太过优秀,任何事情都要亲历亲为才会使它感到放心。举个例子吧,C认为内存实在太重要了,所以一定要程序员自己管理。比如我要创建一个变量,需要先为一个结构体在堆中开辟一片内存空间(malloc)然后将引用这片内存空间的地址传递给变量。一旦这个变量没有用处了,必须销毁并清理这片内存空间(free)。当然,你可以选择不去销毁它。这并没有什么大不了的,顶多运行一段时间就会内存溢出报出和蔼可亲的“段错误”罢了。这时你有两个选择,一、重新开启这个程序。二、老老实实的为每个变量做销毁清理动作。

        也许你觉得这没什么,只是多加一条语句罢了。好吧,也许你只是在写一个helloworld罢了。 当你真正开始用它来做事情的时候,数不清的变量等待着你去为它开辟/销毁,并且有些变量相互引用,我想这并不是一件简单的工作。

        这时新生的Java出现了。与C相对应的,Java认为内存管实在太重要了,所以一定要自己管理。所有C程序员激动的内牛满面。。。 这就是GC对世界带来的变革。

        使用了Java程序员腰不酸了,腿不疼了,一口气写一片,一行顶过去5行。。。

 

    GC对Java带来的福利 :

        说起GC所带来的好处,大家可能这样觉得,不就是可以自动清理没用的对象(内存空间)么。如果你真这样觉得,我想我应该很负责任的告诉你,孩子。。其实你什么都不懂。。

         好吧,不绕弯子了。直接告诉你,那就是对内存创建和清除的速度优化!不可思议吧,一个清理内存系统居然会和创建内存空间的速度有关系。事实上确实如此,由于JVM的清理机制,使得大部分JVM上堆的实现和以前完全不同了,这里我们做一个对比。

 

        *在之前的各种语言中:

            如果你想要创建或者说开辟一片内存空间,要分三步,第一步把冰箱门打开。呃。。。第一步计算变量(对象/结构)的数据大小。第二步在堆中迭代查找足够大的一片内存空间。第三步在这片内存空间中创建变量(对象/结构)并把它的地址(引用/句柄。。反正就是这种东西了。。你懂的)传递给处于栈内的声明式变量(或者叫引用)。

        *在Java中 :

            现在你要创建一片开辟一片内存空间,只需要把堆的指针向下移动一格即可,就像一个链表一样。这与之前的“大杂院”堆开辟一片内存空间的速度完全不在一个次元!而着种改变实际上都应该归功于GC。是它促使了这种改变,使得Java在堆中创建对象可以和之前的一些语言在栈中创建的速度相媲美。一方面Java的堆的指针向下移动分配空间,另一方面GC清理内存空间并使它变的紧凑。这样,我们便拥有了近乎无限的、快速的可供分配堆模型。

 

    Sun早期版本中的GC实现 :

        在JVM早期,GC的实现还没有现在的分代那么完整,或者说是阉割版分代算法。它分为几个算法模式 :

 

        * 引用计数器算法

            引用计数器算法通常用来描述垃圾回收的工作机制,它是一个简单但代价高昂并有缺陷的算法。虽然经常用它来解释垃圾回收是如何工作的,但是至今未被任何JVM实现采用。但是,如果你有兴趣了解垃圾回收算法的编年史还是需要知道它的。

            引用计数器是作用在堆中的对象的,一旦一个对象被引用一次,计数器的数值就会+1,反之则会-1。一旦引用计数器数值为0,就表示这个对象已经无用了,自然会被回收。但是它的缺陷是对象中循环引用的关系,试想一下,如果对象和对象之间互相嵌套,并相互引用,可能会导致一个对象应该被回收,但是它的引用计数器不为0。这就是导致至今它都未被应用于任何JVM中的一个致命元素。

 

        *自适应垃圾回收算法

            自适应式垃圾回收算法起始是引用计数器的逆向思维,它不去记录对象到底被多少对象所引用,而是监测全部局部变量,静态变量等有没有引用一个对象,如果没有,则那些对象必定是没有用的,这就解决了对象之间循环引用的问题。这么做的思想是“如果一个对象的生命周期没有结束,则它一定会追朔到【活在】栈或静态区域的引用”。那么自适应在哪里呢 ? 在于它还有着两种模式:停止--复制、标记--清扫。

            停止--复制: 这种模式会先暂停程序将存活的对象从一个堆复制到令一个堆(你可以想想虚拟机将堆分成了很多块,事实上也是如此,堆中被分配了很多区域)没有被复制的全部都是垃圾,在这之后将被全部销毁。复制到令一个堆之后需要修正引用地址,它的好处是,清理之后堆中对象时一个挨着一个的。(上述的堆实现提到过很多JVM种堆的实现就想一个链表一样)但是缺点也很明显,大量的复制,会有严重的效率问题。所以会有另一种模式。

            标记--清扫: 这种模式同样会先暂停程序,并循环遍历栈和静态区内的所有对象的引用,一旦找到一个存活的对象便会给这个对象加上一个标记,结束后,清理掉所有没有被标记的对象。这种方式是最常被使用的清理方式,因为一旦程序稳定运行,只会产生少量垃圾或者没有垃圾。一旦你了解这种方式基本不会产生什么垃圾,就会体会到这种方式是很迅速的。但是速度的代价就是这种方式清理过后堆中的对象并不是连续的,如果想要连续则需要对剩下的对象进行一个整理的动作。

            说到停止--复制,在大多数JVM实现中,并不会复制全部对象,因为这些JVM的堆实现中,堆分为很多块,很大的对象会独占一个块,其他较小的对象会被复制到已经废弃的块中去(你可以想象有很多个花盆,花花草草的一起种在一个盆里,像木头那种就要自己一个盆了)。这样,就可以减少不必要的浪费(当然每个块中都有一个记录块中对象是否被引用的计数)。这样对于清理很多短命的局部对象时很有用的。

            说到自适应,是因为这两种模式会相互切换。你可以想象一下,在堆中垃圾和碎片并不多的情况下,肯定是会使用标记-清扫这种方式。一旦监测出堆中出现很多碎片或垃圾的时候,就会切换到停止-复制。这是很有用的,急于这两种模式的切换,保证了一个快速的、近乎无限的堆的实现,并保证了垃圾回收的质量。

 

        以上就是sun早期的一些GC实现,尽管不是很详细,但我想大家已经清楚设计者的思路了吧。在现在,已经有了很多替代者实现了更高效、更人性化的GC实现。下一篇将写一个现代JVM中最常被使用的算法----分代回收算法。

分享到:
评论

相关推荐

    com-sun-tools-visualvm-modules-visualgc.zip

    理解并有效利用VisualGC插件,开发者可以更好地调整JVM参数,例如设置合适的堆大小、选择合适的GC算法、优化对象分配策略等,从而提高应用的性能和稳定性。在实际操作中,我们需要结合应用的业务特点和负载情况,...

    JVM内存管理-GC模型-编写GC友好的代码.pdf

    - **常见GC算法**: - **标记-清除算法**: 分为标记和清除两个阶段。标记阶段标记出所有从GC Roots可达的对象;清除阶段清除未被标记的对象。这种算法存在空间碎片化的问题。 - **标记-整理算法**: 在标记清除之后...

    Java_GC垃圾回收调优指南

    在Java开发过程中,垃圾回收(Garbage Collection, GC)是管理内存资源的关键技术之一。合理的GC配置可以显著提高应用程序的性能和稳定性。本指南旨在帮助开发者深入理解Java GC的工作原理,并提供一系列调优策略与...

    JAVA-JVM-全面/发展史/GC.zip

    这个压缩包“JAVA-JVM-全面/发展史/GC.zip”显然包含了关于Java、JVM、垃圾回收(GC)及其历史的深入学习资料,特别是通过“JAVA-笔记.pdf”这样的文档形式。 Java的发展史可以追溯到1991年,由Sun Microsystems的...

    java虚拟机中gc的基本原理 .docx

    在Java中,对象的可达性分析通常基于有向图,通过追踪对象间的引用关系来判断对象是否可达。一旦确定对象不可达,GC就会回收该对象占用的内存空间。 然而,由于Java规范并没有明确规定GC的具体实现,比如采用何种...

    Java Garbage Collection 与各种GC算法.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    Java GC 专题

    为了理解垃圾收集为什么会暂停JVM,首先需要了解Java中垃圾收集的工作原理。 Java虚拟机提供了多种垃圾收集算法,不同的JVM实现可能会使用不同的垃圾收集策略。理解这些垃圾收集策略对于优化垃圾收集行为,减少应用...

    java-virtual-machine-neutral

    在Java中,内存管理是一项自动化任务,由JVM负责。这对于开发者来说是一大优势,但也意味着应用服务器部署团队需要理解并合理配置JVM参数以确保最佳性能和稳定性。 - **Java堆**:Java堆是JVM管理的最大内存区域之...

    从JVM的内存管理角度分析Java的GC垃圾回收机制.docx

    HotSpot JVM的实现采用了Train GC算法,通过对象分组和分层,优先回收最老且访问频率较低的对象。 【finalize方法】 `finalize`是Java中Object类的一个受保护的方法,用于在对象被回收前执行一些清理工作。开发者...

    Sun JVM原理与内存管理

    #### 七、不同GC算法 1. **串行GC** (Serial Copying): - 单线程进行垃圾回收。 - 在 client 模式下默认使用。 - 适合于单核处理器或轻负载的应用场景。 2. **并行回收GC** (Parallel Scavenge): - 多线程...

    优秀的Java程序员必须了解GC的工作原理

    HotSpot JVM中的增量式GC采用了Train GC算法,该算法将堆中的对象按创建和使用频率进行分组。当GC运行时,它会优先回收最老的对象组,以减少程序的整体停顿时间。 #### 三、详解`finalize()`函数 `finalize()`方法...

    JVM_GC调优

    ### JVM_GC调优详解 #### 一、JVM体系结构概览 ...理解不同GC算法的特点和适用场景,可以帮助开发者选择最适合特定应用场景的垃圾回收策略。同时,掌握JVM内存模型和垃圾回收器的工作原理也是进行有效调优的基础。

    优秀Java程序员必须了解的GC工作原理

    然而,Java规范并没有规定具体的GC算法和回收时机,这使得不同JVM实现的GC行为可能有所不同,给程序性能带来不确定性。 为了平衡程序运行的中断(停顿时间)和内存回收的效率,一种常见的解决方案是增量式GC...

    2008年sun深圳站培训资料

    - Java中的对象通过根对象(如全局变量、静态变量等)可达性来确定是否存活。 #### 四、垃圾回收器调优详解 **垃圾回收器算法分析** 1. **标记-清除收集器 (Mark-Sweep Collector)** - **优点**: - 实现简单。...

    JVM深入解析(JVM specification 和Sun的JVM的内存机制)

    - 主要有几种GC算法,如复制算法(年轻代)、标记-整理算法(老年代)、标记-清除算法,以及分代收集。 - CMS(Concurrent Mark Sweep)和G1 GC是现代JVM中常用的并发垃圾收集器,它们在减少停顿时间方面表现出色...

    Sun JDK 1.6内存管理--调优篇

    垃圾收集(Garbage Collection, GC)是Java的一大特点,Sun JDK 1.6支持多种GC算法,如Serial GC、Parallel GC、CMS(Concurrent Mark Sweep)和G1(Garbage-First)。Serial GC适用于单CPU环境,采用单线程进行垃圾...

    jvm gc jvm调优 查看工具

    GC的工作机制包括新生代、老年代、永久代(在较新版本的JVM中已被元空间取代)等区域的划分,以及各种GC算法如复制算法、标记-清除算法、标记-整理算法和分代收集策略等。理解这些机制对于优化JVM性能至关重要。 ...

    java虚拟内存.pdf

    - 分代收集(Generational Collecting):结合多种算法,如在年轻代中使用复制算法,在老年代中使用标记-整理或并发标记-清除算法。 9. JVM监控和性能调整工具: - jconsole:用于监控Java虚拟机以及MBeans(Java...

Global site tag (gtag.js) - Google Analytics