先看如下代码:
Objet obj = new Object();
变量obj是一个内存,new Object()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址(即保存着对象的引用)。变量是放在栈里的,而对象是放在堆里的。所以上面的语句,obj变量放在栈里,保存着Object对象的引用(Object对象在堆中的首地址),而new Object()是在堆上申请了一块内存,这块内存放着Object这个对象。
变量一般是有存活时间的。比如,一个方法内的变量只存活在这个方法内,也就是出了这个方法,这个变量就不存在了。那么,问题来了。当变量已经不存在时,它引用的对象实际上已经没有存在的意义,可是对象却还在堆上存在。C++在变量即将失效时要求程序员自己来释放存放在堆上的对象(在析构函数里利用delete )。而JAVA却要求程序员不管在堆上的对象。也就是说,不需要程序员自己来释放堆上的对象。这些无用的对象就像垃圾一样,那么,就没有一个清洁工来打扫一下,来保持内存的干净么?答案是有,那就是垃圾回收器(GC)。
当然,GC并不会一直运行,就像清洁工不会一天24小时打扫街道一样。它只会在堆即将放满时,才开始垃圾回收操作。当GC开始垃圾回收时,它要处理的第一个问题就是判断哪些是垃圾哪些不是垃圾。一般来说会有下面两种算法:
引用计数算法(Reference Counting)
最初的想法,也是很多教科书判断对象是否存活的算法是这样的:给对象中添加一个引用计数器,当有一个地方引用它,计数器加1,当引用失效,计数器减1,任何时刻计数器为0的对象就是不可能再被使用的。
客观的说,引用计数算法实现简单,判定效率很高,在大部分情况下它都是一个不错的算法,但引用计数算法无法解决对象循环引用的问题。举个简单的例子:对象A和B分别有字段b、a,令A.b=B和B.a=A,除此之外这2个对象再无任何引用,那实际上这2个对象已经不可能再被访问,但是引用计数算法却无法回收他们。
根搜索算法(GC Roots Tracing)
在实际生产的语言中(Java、C#、甚至包括前面提到的Lisp),都是使用根搜索算法判定对象是否存活。算法基本思路就是通过一系列的称为“GC Roots”的点作为起始进行向下搜索,当一个对象到GC Roots没有任何引用链(Reference Chain)相连,则证明此对象是不可用的。在Java语言中,GC Roots包括:
1.在VM栈(帧中的本地变量)中的引用
2.方法区中的静态引用
3.JNI(即一般说的Native方法)中的引用
生存还是死亡?
判定一个对象死亡,至少经历两次标记过程:如果对象在进行根搜索后,发现没有与GC Roots相连接的引用链,那它将会被第一次标记,并在稍后执行他的finalize()方法(如果它有的话)。这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束。这点是必须的,否则一个对象在finalize()方法执行缓慢,甚至有死循环什么的将会很容易导致整个系统崩溃。finalize()方法是对象最后一次逃脱死亡命运的机会,稍后GC将进行第二次规模稍小的标记,如果在finalize()中对象成功拯救自己(只要重新建立到GC Roots的连接即可,譬如把自己赋值到某个引用上),那在第二次标记时它将被移除出“即将回收”的集合,如果对象这时候还没有逃脱,那基本上它就真的离死不远了。
需要特别说明的是,这里对finalize()方法的描述可能带点悲情的艺术加工,并不代表笔者鼓励大家去使用这个方法来拯救对象。相反,笔者建议大家尽量避免使用它,这个不是C/C++里面的析构函数,它运行代价高昂,不确定性大,无法保证各个对象的调用顺序。需要关闭外部资源之类的事情,基本上它能做的使用try-finally可以做的更好。
在确定了哪些对象是垃圾后,GC就可以开始垃圾回收了。
1.“标记-清除算法”(Mark-Sweep)
我们在标记号哪些是垃圾后,就可以开始回收所有需要回收的对象。这就是标记--清除算法,它的主要缺点有两个,一是效率问题,标记和清理两个过程效率都不高,二是空间问题,标记清理之后会产生大量不连续的内存碎片,空间碎片太多可能会导致后续使用中无法找到足够的连续内存而提前触发另一次的垃圾搜集动作。
2.“复制”(Copying)搜集算法
为了解决效率问题,一种称为“复制”(Copying)的搜集算法出现,它将可用内存划分为两块,每次只使用其中的一块,当半区内存用完了,仅将还存活的对象复制到另外一块上面,然后就把原来整块内存空间一次过清理掉。这样使得每次内存回收都是对整个半区的回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存就可以了,实现简单,运行高效。只是这种算法的代价是将内存缩小为原来的一半,未免太高了一点。
3.“标记-整理”(Mark-Compact)算法
复制收集算法在对象存活率高的时候,效率有所下降。更关键的是,如果不想浪费50%的空间,就需要有额外的空间进行分配担保用于应付半区内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法。因此人们提出另外一种“标记-整理”(Mark-Compact)算法,标记过程仍然一样,但后续步骤不是进行直接清理,而是令所有存活的对象一端移动,然后直接清理掉这端边界以外的内存。
4.“分代收集”(Generational Collecting)算法
当前商业虚拟机的垃圾收集都是采用“分代收集”(Generational Collecting)算法,这种算法并没有什么新的思想出现,只是根据对象不同的存活周期将内存划分为几块。一般是把Java堆分作新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法,譬如新生代每次GC都有大批对象死去,只有少量存活,那就选用复制算法只需要付出少量存活对象的复制成本就可以完成收集。
分享到:
相关推荐
C#的垃圾回收机制(GC)是.NET框架中一个至关重要的特性,它负责自动管理和释放内存,从而减轻程序员的工作负担。GC的主要目标是回收不再使用的对象所占用的内存,以防止内存泄漏。在这个机制下,程序员无需手动管理...
Java垃圾回收GC机制 Java垃圾回收GC机制是Java虚拟机(JVM)中的一种自动内存管理机制,它主要是为了解决Java程序中的内存问题。GC机制的出现使得Java程序员不再需要手动管理内存,提高了开发效率和程序的稳定性。 ...
【C#垃圾回收机制GC】深入解析 垃圾回收(Garbage Collection, GC)是现代编程语言中用于自动管理内存的一种机制。它的核心思想是通过跟踪和回收那些不再被程序引用的对象,以避免内存泄漏和提高内存利用率。在.NET...
Java虚拟机(JVM)的垃圾回收(GC)机制是Java程序高效运行的关键部分,它自动管理内存,释放不再使用的对象以避免内存泄漏。本文主要探讨JVM堆内存的结构和GC的工作原理,以及如何进行性能调优。 JVM堆是Java应用...
### Java GC垃圾回收调优指南 #### 概述 在Java开发过程中,垃圾回收(Garbage Collection, GC)是管理内存资源的关键技术之一。合理的GC配置可以显著提高应用程序的性能和稳定性。本指南旨在帮助开发者深入理解...
Java垃圾回收(GC)机制是Java语言管理内存的自动化机制,它能够自动释放不再使用的内存空间,从而避免内存泄漏和程序崩溃等问题。在介绍Java GC机制之前,我们首先要了解垃圾回收的目的和意义。在任何程序中,内存...
Java垃圾回收GC.xmind
Java垃圾回收(GC)机制是Java编程语言中的一个重要特性,它自动管理程序的内存空间,负责识别并清除不再使用的对象,以防止内存泄漏。本文将深入探讨Java GC的工作原理、类型、过程以及优化策略。 一、Java垃圾...
Java垃圾回收(Garbage Collection, 简称GC)是JVM(Java Virtual Machine)管理内存的重要机制。在Java应用程序运行过程中,如果发现并回收不再使用的对象,可以防止内存泄漏,确保程序稳定运行。当我们遇到应用...
GC 垃圾回收机制 GC 垃圾回收机制是 .NET 中一个复杂的机制,对于提高程序性能和减少内存泄露非常重要。CLR 垃圾回收器根据所占空间大小划分对象,大对象和小对象的处理方式有很大区别。 大对象堆和垃圾回收 在 ...
GC总结
在.NET Framework环境中,虽然开发人员不必直接管理内存和处理垃圾回收(Garbage Collection, GC),但了解这些底层机制对于优化应用程序至关重要。这不仅能提升程序的性能,还能帮助开发者更好地理解程序变量的行为...
迷你垃圾回收器(Mini GC for C)是一种针对C语言实现的轻量级内存管理工具,主要功能是自动回收不再使用的内存,以防止内存泄漏。在C语言中,程序员需要手动管理内存分配和释放,而垃圾回收器则可以自动化这一过程...
JVM GC垃圾回收.pdfJVM GC垃圾回收.pdfJVM GC垃圾回收.pdfJVM GC垃圾回收.pdfJVM GC垃圾回收.pdf
垃圾回收(Garbage Collection, GC)是指在程序运行过程中自动检测并释放那些不再被使用的对象所占用的内存空间的过程。这一过程通常是由语言的运行环境(如Java虚拟机)自动完成的,而不需要程序员手动干预。 **2....
NETC#栈堆垃圾回收GC借鉴.pdf
垃圾回收(Garbage Collection, GC)是编程语言中用于自动管理内存的重要机制,尤其是在像Java、C#等语言中。这个技术示例旨在深入探讨垃圾回收的原理、工作流程以及在实际开发中的应用。 垃圾回收的基本目标是识别...
Java虚拟机(JVM)的垃圾回收(Garbage Collection, GC)是Java编程语言中一个重要的特性,它自动管理程序的内存,确保无用的对象被有效地释放,避免内存泄漏。理解JVM垃圾回收机制对于优化Java应用性能至关重要。 ...
其中,垃圾回收机制(Garbage Collection, GC)是Java虚拟机(JVM)的一项重要特性,它能够自动检测并回收不再使用的对象占用的内存空间,从而有效避免了内存泄漏问题。本文将详细介绍Java中的垃圾回收机制及其工作原理...