`
solidsnake2007
  • 浏览: 28933 次
  • 性别: 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中最常被使用的算法----分代回收算法。

分享到:
评论

相关推荐

    Java Garbage Collection 与各种GC算法.zip

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

    Java学习笔记

    Java 到底有哪些优势? 1.跨平台(平台=OS) 可移植性 在不同的操作系统之上可以...gc 内存回收清理 Java 中的回收机制: 零引用回收 问题: System.gc(); Runtime.getRuntime().gc(); 调用gc 的下一行是否回收?不一定

    resin-jvm 调优

    java语言并不要求jvm有gc,也没有规定gc如何工作。不过常用的jvm都有gc,而且大多数gc都使用类似的算法管理内存和执行收集操作。 在充分理解了垃圾收集算法和执行过程后,才能有效的优化它的性能。有些垃圾收集专...

    java 面试题 总结

     GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收...

    Java虚拟机

    这本书的内容是帮你全面了解java虚拟机,本书第1版两年内印刷近10次,98%以上的评论全部为5星级的好评,是整个Java图书领域公认的经典著作和超级畅销书,繁体版在台湾也十分受欢迎。第2版在第1版的基础上做了很大的...

    超级有影响力霸气的Java面试题大全文档

     GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收...

    studytoshare:Java基础 ,一个纯新手的快速入门,言简意赅,来自一个自学者的提要。参考和部分转载[http

    1.Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。 2.Java可运行于多个平台,如Windows, Mac OS,及其他多种UNIX版本的系统。 3.Java语言的特点简单、解释性、面向对象、健壮、动态、高性能、多...

    TCPIP详解--共三卷

    29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS...

    TCP_IP详解卷1

    29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS...

    TCPIP详解卷[1].part04

    29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS...

    TCPIP详解卷[1].part09

    29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS...

    TCPIP详解卷[1].part03

    29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS...

    TCPIP详解卷[1].part05

    29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS...

    TCPIP详解卷[1].part06

    29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS...

    TCP/IP详解part_2

    29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS...

    TCPIP详解卷[1].part08

    29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS...

    TCPIP详解卷[1].part11

    29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS...

    TCPIP详解卷[1].part12

    29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS...

    TCPIP详解卷[1].part07

    29.2 Sun远程过程调用 347 29.3 XDR:外部数据表示 349 29.4 端口映射器 349 29.5 NFS协议 351 29.5.1 文件句柄 353 29.5.2 安装协议 353 29.5.3 NFS过程 354 29.5.4 UDP还是TCP 355 29.5.5 TCP上的NFS 355 29.6 NFS...

Global site tag (gtag.js) - Google Analytics