探索JVM自动垃圾回收机制
田海立,系统分析师
<chsdate year="2005" month="8" day="25" islunardate="False" isrocdate="False" w:st="on"><span lang="EN-US">2005</span><span style="font-family: 宋体;">年</span><span lang="EN-US">8</span><span style="font-family: 宋体;">月</span><span lang="EN-US">25</span><span style="font-family: 宋体;">日</span></chsdate>
本文在分析堆空间管理容易出现的问题的基础上,探讨了Java虚拟机(JVM)的自动垃圾回收机制的各种算法。
关键词:堆,垃圾回收,JVM,内存碎片,内存泄漏,悬空引用
<!--[if supportFields]><span
lang=EN-US><span style='mso-element:field-begin'></span><span
style='mso-spacerun:yes'></span>TOC /o "1-3" /h /z /u <span
style='mso-element:field-separator'></span></span><![endif]-->摘要... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112740988 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->1<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340030003900380038000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
目录... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112740989 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->1<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340030003900380039000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
一、堆(Heap)空间管理... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112740990 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->2<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340030003900390030000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
二、问题的提出——为何要实现自动垃圾回收?... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112740991 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->2<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340030003900390031000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
三、垃圾回收算法分析... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112740992 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->3<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340030003900390032000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
3.1 引用计数(Reference Counting)算法... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112740993 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->3<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340030003900390033000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
3.2 追踪(Tracing)回收算法... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112740994 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->3<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340030003900390034000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
3.3 压缩(Compacting)回收算法... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112740995 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->4<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340030003900390035000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
3.4 拷贝(Coping)回收算法... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112740996 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->4<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340030003900390036000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
3.5 分代(Generational)回收算法... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112740997 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->4<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340030003900390037000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
3.6 火车(Train)算法... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112740998 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->4<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340030003900390038000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
3.7 自适应(Adaptive)算法... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112740999 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->5<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340030003900390039000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
四、影响JVM的垃圾回收... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112741000 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->5<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340031003000300030000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
4.1 Object的finalize()方法... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112741001 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->5<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340031003000300031000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
4.2 System中相关的方法... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112741002 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->5<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340031003000300032000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
五、总结... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112741003 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->6<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340031003000300033000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
参考资料... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112741004 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->6<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340031003000300034000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
关于作者... <!--[if supportFields]><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'><span style='mso-element:field-begin'></span></span><span
style='color:windowtext;display:none;mso-hide:screen;text-decoration:none;
text-underline:none'> PAGEREF _Toc112741005 /h </span><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-separator'></span></span><![endif]-->6<!--[if gte mso 9]><xml>
<w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F0054006F0063003100310032003700340031003000300035000000</w:data>
</xml><![endif]--><!--[if supportFields]><span style='color:windowtext;
display:none;mso-hide:screen;text-decoration:none;text-underline:none'><span
style='mso-element:field-end'></span></span><![endif]-->
<!--[if supportFields]><span
lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->
一、堆(Heap)空间管理
堆(Heap)是一个运行时的数据存储区,从它可以分配大小各异的空间。一般,运行时的数据存储区有堆(Heap)和堆栈(Stack),所以要先看它们里面可以分配哪些类型的对象实体,然后才知道如何均衡使用这两种存储区。一般,堆栈里存放的是非static的自动变量、函数参数、表达式的临时结果和函数返回值(如果他们没有被放到寄存器里)。堆栈里的这些实体的分配/释放是由编译系统自动完成的,堆里面存放的实体都是程序里面显式分配的,没有自动垃圾回收机制的系统里面也必须由程序代码显式的释放这些实体。在嵌入式系统中,这些资源都非常有限,尤其是堆栈,我见过的RTOS基本都是给每个Task/Process固定分配一定大小的Stack,因为对堆栈的操作不是由程序自身可以控制的,如果分配的实体如果超出堆栈区域,将会发生灾难性后果。避免堆栈溢出,一般只要遵循几个原则就行了,一、不要分配大的实体到堆栈上;二、避免过深的递归调用;三、注意类型转换(显式的和隐式的)。解决第二条需要算法上的考虑,而解决第一条只要做到把大的对象放到堆上就行了,也就是,如果局部自动变量或者函数参数是一个很大的变量,用一个引用/指针代替,把它分配到堆上,然后针对引用/指针操作,亦即用“引用模式”绕过“值模式”产生的大的实体复制的影响(关于这个话题,就不拓展了^_^)。
堆的管理,不同的语言/系统的实现是不同的。比如c语言就没有把堆的分配/释放做到语言的层次,它对堆空间对象的操作是通过库函数malloc/free来实现的;c的后代做的就比较彻底,c++直接把对堆空间里的对象的分配/释放做到语言层次的new/delete;Java就做得更彻底,应用开发者只要在需要用堆分配的时候创建就行了,何时释放如何释放,都有Java虚拟机(JVM)来做,而不需要程序代码来显式地释放。尽管JVM的Specification并未强求一定要有垃圾回收,也未对采用哪种回收技术做限定,但现在已由的JVM实现基本都实现了自动垃圾回收,有些还实现了很多种回收技术,具体采用哪种或哪几种可以通过配置来决定。
没有实现自动垃圾回收机制的系统里,在堆里申请的实体所占的内存在程序运行的时候将一直被占用,在显式释放之前不能再分配给其它实体。对于全部的Task/Process来说,使用的堆都是同一块区域。看下面情形,有一段代码从堆里申请了一块内存M1;然后申请了一块M2,假定M2紧接着M1;现在释放M1,这样先前M1占着的空间就是空闲的,但是它与其它的空闲区域不是连续的,中间隔着M2。如果M1的大小加上其它的空闲区域的大小为count_free,如果再要申请大于M1,大于其它空闲区域,而小于count_free的空间,就会失败,因为虽然总的剩余空间满足大小要求,但却找不到那么大小的连续区域,这就是所谓的“内存碎片”问题。
使用堆存储空间对编程来说是个便利,也是一个负担,因为使用堆不当可能引起的致命问题:内存泄漏(Leak)或悬空引用(Dangling
Reference)。内存泄漏是指从堆上分配了空间,但在程序生命结束了还没有释放,而这些空间是被标记了被死掉的程序使用的,所以也不能再被其它程序使用,就成为了僵死的(zoombie),时间久了这些死尸没有回收“掩埋”,堆空间迟早会被耗尽,再有分配请求无法正常满足,结果必然导致系统不能正常工作。悬空引用就更危险了,悬空引用是指使用已经不再有效的实体,这些实体可能是使用之前自己把它释放掉了或者赋值给了别人,别人把它释放掉了。现在的系统基本都采取了存储空间的保护措施,悬空引用的也就是访问了分配给别人的空间或者是空闲的空间,结果就会导致系统崩溃。
JVM的自动垃圾回收机制解放了程序员,他们不再在对堆空间管理的泥潭里挣扎,同时也解决可能引起的内存碎片,内存泄漏和悬空引用等问题。但是这项技术的采用也是把双刃剑,自动垃圾回收对于何时进行不能准确把握,一次回收的粒度也不能精确定位,这必然影响系统性能,这些影响在嵌入式系统中尤为突出。早期采用的某些垃圾回收算法也不能保证100%收集到所有的废弃内存,不过随着垃圾收集算法的不断改进以及软硬件运行效率的不断提升,这些问题得以解决或缓解。
任何一种垃圾收集算法都必须要做两件事情:(1)检测出垃圾信息;(2)回收检测出的垃圾所占用的内存空间,把这些空间返还给堆管理器,使之可以再次被程序使用。
3.1 引用计数(Reference Counting)算法
一般来说,引用计数法,堆中的每个对象对有一个引用计数器(Reference Counter)。计数器一般按如下规则赋初值和加减计数。
<!--[if !supportLists]-->-
当创建了一个对象并把指向该对象的引用赋给一个变量时,这个对象的引用计数器就被置为1。<!--[endif]-->
<!--[if !supportLists]-->-
当对象的引用被赋给任意变量时,该对象的引用计数器加1。<!--[endif]-->
<!--[if !supportLists]-->-
当对象的引用超出了生存期或者被设置为新的值的时候,其引用计数器减1。<!--[endif]-->
<!--[if !supportLists]-->-
如果引用计数器为0,该对象就满足了垃圾回收的条件。<!--[endif]-->
采用引用计数的垃圾回收器可以很快的运行,当前的程序不会因为JVM需要运行垃圾回收而被长期中断,比较适合嵌入式实时环境计算。但运行中对引用计数器的加减增加了程序执行的开销。最主要一点,它并不能处理两个或两个以上的对象的交叉引用情况。
3.2 追踪(Tracing)回收算法
追踪回收法会用到JVM维护的对象引用图,从跟节点开始追踪,遇到的对象打上印记。当整个追踪过程结束,未被标记的对象就是无法到达的,是可以被回收的,在某个适当的时候会被回收。因为标记和清楚是分开的过程,而Java暴露出finalize()方法,所以就有可能需要二次扫描,这种情况将在Finalize一节中讲述。
3.3 压缩(Compacting)回收算法
压缩回收算法把堆中的活动对象移动到堆的一端,这样就结果就是在堆的另外一端留出了一个大的空闲区,也就相当于压缩掉了垃圾对象和活动对象之间的碎片。压缩回收算法要求所有被移动对象的引用也要同步更新,指向新的移动后的位置。这一切都是在对程序员透明的情况下,由JVM来做的。
该算法不仅回收了堆里的垃圾,还整理了内存碎片。
3.4 拷贝(Coping)回收算法
拷贝回收算法一般把堆分成两个大小的区域,任何时刻只有一个区域在使用。对象在同一个区域内分配/释放,直到这个区域不能再被分配。此时当前正在运行的程序被中断,扫描使用中的的区域,遇到活动对象就把它拷贝到另外的哪个区域,知道没有活动对象,此时被中止的程序再次运行,而使用的堆是拷贝活动对象到的区域,完成两个区域的转换。拷贝回收算法也要求所有被拷贝对象的引用也要同步更新,指向新的拷贝后的位置。
拷贝算法也是实现了对垃圾的回收和碎片的整理。但是这个算法代价也很高,需要堆空间两倍大的内存;因为要停止当前运行程序进行内存整理,也需要耗费很长的时间,效率很低。分代回收算法可以减缓这种代价。
3.5 分代(Generational)回收算法
分代回收算法就是针对拷贝算法的效率问题做出的改进,它是基于下面两个经验规律的:
<!--[if !supportLists]-->-
大部分对象的生存期都很短;<!--[endif]-->
<!--[if !supportLists]-->-
有些对象的生存期很长。<!--[endif]-->
该算法把对象按他们的寿命进行分组,优先回收年轻的对象。把堆按代分组,每组称做一代。子代里的对象可以转到高一级的代里,如果一个对象经过多次收集仍然存活,把它移到高一级的代的堆里,减少再次扫描它的次数。
3.6 火车(Train)算法
Train算法在堆中老的代和年轻的代之间创建一个新区域。这些堆区域划分为“火车”,每个火车又分为一系列的“车厢”。每个火车车厢组成单独的一代,这意味着不但要跟踪老到年轻的引用,而且还要跟踪从老的火车到年轻的火车以及老的车厢到年轻的车厢的引用。
回收可以针对车也可以针对车厢。回收的时候会把被回收的火车/车厢内被引用的对象都转到其它车/车厢中,剩下的就是垃圾,可以整个火车/车厢的回收了。这个算法提供了对堆空间限定时间内的渐进式回收,可以用在嵌入式实时环境。
火车算法还解决了有交叉引用情形的垃圾回收问题。如果正被回收的车厢内有被来自所管理的火车之外的对象所引用,则把它移到其它特殊的火车里;如果正被回收的车厢内有被所管理的火车之内的其它火车里的对象所引用,则把它移到那列火车;正在被回收的车厢的外部引用都来自同一列火车的其它车厢,则把这样的对象都移到这列火车的最后一列去。重复这个过程,结果就是没有引用指向这节车厢,这节车厢可以被回收了。
3.7 自适应(Adaptive)算法
垃圾回收算法在不同的情况下,工作表现也不同。自适应算法通过监视堆的情形,相应的调整垃圾回收算法。
Java中的垃圾回收是由JVM实现的,如何回收,何时开始回收对程序员来说都是透明的(Transparent),但是程序员可能会影响到垃圾回收工作,也可以请求垃圾回收器开始工作。
Java里所有类的父类Object里有个finalize()方法,它在垃圾回收器认为这个对象是垃圾的之后,真正回收之前执行。所以你在实现这个方法的时候有可能再次使一些对象成为被引用对象,也就影响到了垃圾回收工作。
finalize()的原型如下:
protected
void finalize() throws Throwable
一般在调用这个方法之前,垃圾回收器已经检测出不再被引用的对象;然后如果这些对象声明了finalize方法,就要处理该方法;因为finalize方法可能使某些对象“复活”,回收器必须再次检测不再被引用的对象,两次都不再使用的对象才被回收。
程序员可以通过System类的某些方法来请求开始垃圾回收器或者开始运行不再被引用对象的finalize方法。
它们的原型如下:
public
static void gc();
请求回收器回收不再被引用对象。
public static void
runFinalization();
请求回收器回收不再被引用对象的finalize方法。
通过Runtime同样有System类中的那两个方法的效果。Runtime是个Singleton,通过public static
Runtime getRuntime()获得Runtime的实例,所以Runtime.getRuntime().gc()与System的类方法gc()的效果一样;Runtime.getRuntime().runFinalization()与System的类方法runFinalization()的效果一样。
另外在写代码的时候,把不再使用的引用赋为null也可以方便JVM回收器的工作,当然这并不是必须的。
垃圾自动回收技术仍是目前研究活跃的领域,这篇文章只是分析别人的研究和应用的成果,分析的目的并不是要设计一个垃圾回收器,只是要吸收其中的设计思想,在工作中无形的起到帮助作用。
本来采用那种回收算法,甚至采用回收机制与否的取舍也并没有绝对的标准,思考的角度,评价的标准不同,采取的设计决策当然也就不同。这已经是从哲学角度看问题了——怪不得现在《xxx艺术》(计算机程序设计艺术、UNIX程序设计艺术、汇编程序设计艺术、c++程序设计艺术、Java程序设计艺术、软件架构的艺术,…)这么热卖!^_^
<!--[if !supportLists]-->1.
Bill Venners, Inside the Java
Virtual Machine, 2nd edition <!--[endif]-->
<!--[if !supportLists]-->2.
B.K & D.R, The c
Programming Language, 2nd edition <!--[endif]-->
<!--[if !supportLists]-->3.
Bjarne Stroustrup, The c++
Programming Language, 3rd special Edition, Addison Wesley<!--[endif]-->
<!--[if !supportLists]-->4.
Ken
Arnold, James Gosling, David Holmes, The Java
Programming Language, 3rd Edition<!--[endif]-->
<!--[if !supportLists]-->5.
Michael L. Scott, Programming Language Pragmatics<!--[endif]-->
田海立(IT小混混),系统分析师,2004年硕士毕业于南京大学(软件架构方向),主要兴趣:嵌入式系统应用架构,Java/Eclipse,Linux技术,攻读硕士之前和目前都从事嵌入式系统研发。您可以通过haili.tian@gmail.com
与他联系,到 http://blog.csdn.net/thl789/ 或 http://spaces.msn.com/members/thl789 看他的文章。
(本文可自由转载,但请给出原文链接: http://blog.csdn.net/thl789/archive/2005/08/29/467412.aspx)。
分享到:
相关推荐
【JAVA·初级】GC垃圾回收机制是Java编程中一个至关重要的概念,对于任何Java开发者来说,理解并掌握这一机制都是提升程序性能的关键。在Java中,内存管理主要依赖于垃圾回收器(Garbage Collector,简称GC),它...
《深入理解JVM性能调优和内存模型,垃圾回收,虚拟机原理,经典视频教程》是一套详尽的教育资源,旨在帮助Java开发者深入探索Java虚拟机(JVM)的内部工作机制,提升性能优化的能力。本教程共包含110讲,内容丰富,适合...
Java虚拟机(JVM)是Java平台的核心,它负责执行字节码,提供了内存管理、类加载、垃圾回收等功能,确保了Java的“一次编写,到处运行”的特性。JVM通过解析.class文件中的字节码,将其转换为机器码,从而在本地操作...
- **垃圾回收机制**:JVM通过自动垃圾回收机制来管理对象的生命周期,了解其工作原理有助于优化内存使用。 - **类加载机制**:类加载是JVM启动后的一个重要环节,理解类加载过程对于解决类加载问题具有重要意义。 ...
2. **垃圾回收**:Java的自动内存管理主要依赖于垃圾回收机制。Java8中引入了G1(Garbage-First)垃圾收集器,它是并行和并发的,目标是减少垃圾回收停顿时间。还有其他如CMS(Concurrent Mark Sweep)和Parallel/...
**2.4 垃圾回收机制** 垃圾回收(Garbage Collection,GC)是自动回收不再使用的对象,从而释放内存空间的过程。JVM提供了几种不同的垃圾收集算法来处理不同情况下的内存回收需求。 #### 三、JVM性能调优 **3.1 GC...
在设计JVM时,考虑到Java语言的特点,如面向对象、自动垃圾回收等特性,JVM的设计需要能够支持这些特性。 ##### 如何检查JVM代码 可以使用`javap`工具来反汇编已编译的Java类文件,查看字节码指令。例如,如果想要...
1. **堆内存**: 分为新生代和老年代,使用垃圾收集机制自动回收无用对象。新生代采用复制算法,老年代通常使用标记-整理或标记-压缩算法。 2. **新生代细粒度划分**: 包括Eden空间、From Survivor和To Survivor空间...
垃圾收集自动回收不再使用的对象,避免内存泄漏。常见的垃圾收集算法有标记-清除、复制、标记-整理和分代收集等。内存分配涉及对象在堆中的布局,如对象头、实例数据和对齐填充。 5. **JVM调优**:通过调整JVM参数...
4. **垃圾收集**:JVM的内存管理主要包括自动垃圾收集,它通过标记-清除、复制、标记-整理和分代收集等算法来回收无用对象占用的内存。JVM提供了不同的垃圾收集器,如Serial、ParNew、CMS、G1等,它们各有优缺点,...
例如,类装载器负责加载类到JVM,而运行时数据区包括堆内存、栈内存、方法区等,其中垃圾回收机制是优化的重要一环。 接着,深入理解JVM内存模型至关重要。Java对象在堆内存中分配,而栈内存存储方法的局部变量。...
4. **垃圾回收**:JVM自动进行垃圾回收,释放不再使用的对象所占用的内存。GC(Garbage Collection)策略包括标记-清除、复制、标记-整理和分代收集等。理解GC的工作原理和调优技巧可以避免不必要的系统停顿,提高...
JVM的垃圾收集是自动管理内存的过程,主要目标是回收不再使用的对象所占用的内存空间。常见的垃圾收集算法有: 1. **标记-清除(Mark-Sweep)**:标记所有活动对象,然后清除未标记的对象。 2. **复制(Copying)**:将...
JVM的垃圾收集机制自动回收不再使用的对象所占用的内存,主要包括新生代、老年代、持久代。常见的垃圾收集算法有标记-清除、复制、标记-整理和分代收集等。JVM提供了多种垃圾收集器,如Serial、Parallel、CMS、G1等...
Java的垃圾收集机制自动管理堆内存,通过不同类型的垃圾收集器来实现内存回收,如串行、并行、并发和G1垃圾收集器。 1.3 Java虚拟机的特性 JVM的一个重要特性是它的即时编译器(JIT),它能够在运行时将频繁执行的...
**JVM学习笔记(Java虚拟机)** Java虚拟机(JVM)是Java语言的核心组成部分,它是Java程序运行的平台,负责解释和执行字节码。深入理解JVM对于优化Java应用...不断探索JVM的细节,有助于成为一名优秀的Java开发者。
4. **垃圾回收**:JVM自动管理内存,通过垃圾回收机制回收不再使用的对象所占用的空间,避免内存泄露。 在JVM的内存结构中,主要有以下几个区域: - **方法区**(Method Area):存储类信息、常量、静态变量等。 - ...
GC是自动内存管理的重要部分,它负责识别并回收不再使用的对象,以避免内存泄漏。常见的垃圾收集算法有: 1. **标记-清除(Mark-Sweep)**:标记所有活动对象,然后清除未标记的对象。 2. **复制(Copying)**:将...