Logo

郎哥编程

垃圾收集器

2020-01-07 219

垃圾收集器(Garbage Collection)通常被称为GC,它用于回收在堆中不再使用的实例对象和数组占用的内存空间。除了释放不再被引用的对象外,它还负责对堆中内存进行碎片整理,将多个碎片内存区域整理成一块较大的内存区域,提供堆中内存的利用效率。

GC需要一种算法来判断堆中的实例对象是否可以被释放:当实例对象不再被有效变量引用时,这些实例对象是可以被释放的;当实例对象正在被有效变量引用时,这些实例对象是不能被释放的。

引用计数是GC使用比较早的一种算法。在这种算法中,每个实例对象都有一个引用计数,当对象在堆中创建后,并且对象的引用被赋值给一个变量,这个对象的引用计数就加1。当引用的变量被释放或被赋予一个新的对象引用后,该对象的引用计数就减1,对象的引用计数变为0后,GC就会认为这个对象是可以被释放的。引用计数算法虽然简单,但会存在循环引用的问题,即两个或者更多的对象相互引用。例如:父对象有一个对子对象的引用,子对象又反过来引用父对象,就会导致这些对象的计数不可能变为0。因此引用计数的算法在虚拟机中已经很少使用了。

目前主流的虚拟机大多采用分区收集算法。它根据对象的存活周期的不同而将内存分为几块,分别为新生区、老年区和静态区。新生区的对象生存期短,每次回收都会有大量对象被释放(例如方法的局部变量等);老年区里的对象存活率较高(例如类变量等);静态区里的对象创建后几乎不用释放(如Class对象、静态变量等)。

GC的触发机制

GC有两种类型:Full GC 和Scavenge GC。

1、Full GC

GC在优先级最低的线程中运行,一般在线程空闲时(即没有线程在运行)被调用。GC会对整个堆进行整理,包括新生区、老年区和静态区。Full GC因为需要对整个堆进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。

2、Scavenge GC

(1)当堆内存不足时,会触发Scavenge GC调用,释放堆中不再被变量引用的实例对象或数组;

(2)线程在运行过程中创建新对象,若这时堆空间不足,JVM就会强制调用Scavenge GC线程。若GC一次之后仍不能满足内存分配,JVM会再进行两次GC,若仍无法满足要求,则JVM将报“out of memory”的错误,虚拟机将停止运行,程序也会停止运行。

GC的两个重要方法

1、System.gc()方法

程序调用System.gc()方法,可以触发GC进行一次垃圾回收。

2、finalize()方法

该方法用于在GC释放一个对象之前,会调用finalize()方法释放对象用到的资源。如果程序要释放对象用到的资源,需要重写父类的finalize()方法,Object类定义了finalize()方法。

代码在线纠错(通义千问 qwen-max)

支持粘贴多个代码文件,提交后由阿里云通义千问自动分析代码漏洞、语法错误、逻辑问题并给出修改建议。
您已解锁 AI 代码纠错功能,可正常使用!

评论区

登录 后发表评论
暂无评论