首页 > 技术文章 > GC是什么?为什么要有GC?

gdutcaleb 2017-03-07 21:20 原文

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

GC是垃圾收集器。Java 程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:  
System.gc() 
Runtime.getRuntime().gc() 

Java是由C++发展来的。

它摈弃了C++中一些繁琐容易出错的东西。其中有一条就是这个GC。

写C/C++程序,程序员定义了一个变量,就是在内存中开辟了一段相应的空间来存值。内存再大也是有限的,所以当程序不再需要使用某个变量的时候,就需要释放这个内存空间资源,好让别的变量来用它。在C/C++中,释放无用变量内存空间的事情要由程序员自己来解决。就是说当程序员认为变量没用了,就应当写一条代码,释放它占用的内存。这样才能最大程度地避免内存泄露和资源浪费。

但是这样显然是非常繁琐的。程序比较大,变量多的时候往往程序员就忘记释放内存或者在不该释放的时候释放内存了。而且释放内存这种事情,从开发角度说,不应当是程序员所应当关注的。程序员所要做的应该是实现所需要的程序功能,而不是耗费大量精力在内存的分配释放上。

Java有了GC,就不需要程序员去人工释放内存空间。当Java虚拟机发觉内存资源紧张的时候,就会自动地去清理无用变量所占用的内存空间。当然,如果需要,程序员可以在Java程序中显式地使用System.gc()来强制进行一次立即的内存清理。

GC的执行机制

由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。GC有两种类型:Scavenge GC和Full GC。

Scavenge GC

一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来。

Full GC

对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个对进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。在对JVM调优的过程中,很大一部分工作就是对于FullGC的调节。有如下原因可能导致Full GC:

  1.年老代(Tenured)被写满

  2.持久代(Perm)被写满

  3.System.gc()被显示调用

  4.上一次GC之后Heap的各域分配策略动态变化

 

因为显式声明是做堆内存全扫描,也就是 Full GC,是需要停止所有的活动的(Stop The World Collection),你的应用能承受这个吗?而其显示调用System.gc()只是给虚拟机一个建议,不一定会执行,因为System.gc()在一个优先级很低的线程中执行。 

 

首先JAVA和ASP.NET都有GC 

垃圾回收   (garbage   collection,   GC)      
  一个跟踪过程,它传递性地跟踪指向当前使用的对象的所有指针,以便找到可以引用的所有对象,然后重新使用在此跟踪过程中未找到的任何堆内存。公共语言运行库垃圾回收器还压缩使用中的内存,以缩小堆所需要的工作空间 

因为你没有足够多内存,并且,你挺懒,不去自己清理内存,所以就有了   GC 



什么是GC 
GC的全称是garbage collection,中文名称垃圾回收,是.net中对内存管理的一种功能。垃圾回收器跟踪并回收托管内存中分配的对象,定期执行垃圾回收以回收分配给没有有效引用的对象的内存。当使用可用内存不能满足内存请求时,GC会自动进行。 

在进行垃圾回收时,垃圾回收器回首先搜索内存中的托管对象,然后从托管代码中搜索被引用的对象并标记为有效,接着释放没有被标记为有效的对象并收回内存,最后整理内存将有效对象挪动到一起。这就是GC的四个步骤。 

由上可见,GC是很影响性能的,所以一般说来这种事情况还是尽量少发生为好。 

为了减少一些性能影响,.net的GC支持对象老化,或者说分代的概念,代是对象在内存中相对存现时期的度量单位,对象的代数或存现时期说明对象所属的代。目前.net的垃圾回收器支持三代。每进行一次GC,没有被回收的对象就自动提升一代。较近创建的对象属于较新的代,比在应用程序生命周期中较早创建的对象的代数低。最近代中的对象位于零代中。每一次GC的时候,都首先回收零代中的对象,只有在较低代数的对象回收完成后仍不能满足需求的情况下才回收较高代数的对象。

推荐阅读