java垃圾回收机制是怎样的

发布时间:2022-05-24 23:47:25

手动管理内存

在介绍现代版的垃圾回收之前,我们先来简单地回顾下需要手动地显式分配及释放内存的那些日子。如果你忘了去释放内存,那么这块内存就无法重用了。这块内存被占有了却没被使用。这种场景被称之为内存泄露。

下面是用C写的一个手动管理内存的简单例子:

intsend_request()

{

size_tn=read_size();

int*elements=malloc(n*sizeof(int));

if(read_elements(n,elements)<n)

{//elementsnotfreed!return-1;}//…free(elements)

return0;}

可以看到,你很容易就会忘了释放内存。内存泄露曾经是个非常普遍的问题。你只能通过不断地修复自己的代码来与它们进行抗争。因此,需要有一种更优雅的方式来自动释放无用内存,以便减少人为错误的可能*。这种自动化过程又被称为垃圾回收(简称GC)。

智能指针

自动垃圾回收早期的一种实现便是引用计数。你知晓每一个对象被引用了几次,当计数器归0的时候,这个对象就可以被安全地回收掉了。C++的共享指针就是一个非常着名的例子:

11intsend_request(){size_tn=read_size();stared_ptrelements=make_shared();if(read_elements(n,elements)<n){return-1;}return0;}

我们使用的sharedptr会记录这个对象被引用的次数。如果你将它传递给别人则计数加一,当它离开了作用域后便会减一。一旦这个计数为0,sharedptr会自动地删除底层对应的vector。当然这只是个示例,因为也有读者指出来了,这个在现实中是不太可能出现的,但作为演示是足够了。

自动内存管理

在上面的C++代码中,我们还得显式地声明我们需要使用内存管理。那如果所有的对象都采用这个机制会怎样呢?那简直就太方便了,这样开发人员便无需考虑清理内存的事情了。运行时会自动知晓哪些内存不再使用了,然后释放掉它。也就是说,它自动地回收了这些垃圾。第一代的垃圾回收器是1959年Lisp引入的,这项技术迄今为止一直在不断演进。

引用计数

刚才我们用C++的共享指针所演示的想法可以应用到所有的对象上来。许多语言比如说Perl,Python以及PHP,采用的都是这种方式。这个通过一张图可以很容易说明:

绿*的云代表的是程序中仍在使用的对象。从技术层面上来说,这有点像是正在执行的某个方法里面的局部变量,亦或是静态变量之类的。不同编程语言的情况可能会不一样,因此这并不是我们关注的重点。

蓝*的圆圈代表的是内存中的对象,可以看到有多少对象引用了它们。灰*圆圈的对象是已经没有任何人引用的了。因此,它们属于垃圾对象,可以被垃圾回收器清理掉。

看起来还不错对吧?没错,不过这里存在着一个重大的缺陷。很容易会出现一些孤立的环,它们中的对象都不在任何域内,但彼此却互相引用导致引用数不为0。下面便是一个例子:

看到了吧,红*部分其实就是应用程序不再使用的垃圾对象。由于引用计数的缺陷,因此会存在内存泄露。

有几种方法可以解决这一问题,比如说使用特殊的“弱”引用,或者使用一个特殊的算法回收循环引用。之前提到的Perl,Python以及PHP等语言,都是使用类似的方法来回收循环引用的,不过这已经超出本文讲述的范围了。我们准备详细介绍下JVM所采用的方法。

标记删除

首先,JVM对于对象可达*的定义要明确一些。它可不像前面那样用绿*的云便含煳了事的,而是有着非常明确及具体的垃圾回收根对象(GarbageCollectionRoots)的定义:

局部变量

活动线程

静态字段

JNI引用

其它(后面将会讨论到)

JVM通过标记删除的算法来记录所有可达(存活)对象,同时确保不可达对象的那些内存能够被重用。这包含两个步骤:

标记是指遍历所有可达对象,然后在本地内存中记录这些对象的信息

删除会确保不可达对象的内存地址可以在下一次内存分配中使用。

JVM中的不同GC算法,比如说ParallelScavenge,ParallelMark+Copy,CMS都是这一算法的不同实现,只是各阶段略有不同而已,从概念上来讲仍然是对应着上面所说的那两个步骤。

这种实现最重要的就是不会再出现泄露的对象环了:

缺点就是应用程序的线程需要被暂停才能完成回收,如果引用一直在变的话你是无法进行计数的。这个应用程序被暂停以便JVM可以收拾家务的情况又被称为StopTheWorldpause(STW)。这种暂停被触发的可能*有很多,不过垃圾回收应该是最常见的一种。

看了java垃圾回收机制是怎样的还看了:
  • 总结Java垃圾回收器的方法和原理

    说到垃圾回收(GarbageCollection,GC),很多人就会自然而然地把它和Java联系起来。在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM来处理。顾名思义,垃圾回收就是释放垃圾占用的空间,那么在...

  • 垃圾员工是怎样形成的

    垃圾员工画像或许你不会陌生,在企业这个应该体现效率的组织里面,总会有这样一群人,你打电话问他或者找他办一些事情,他?她?总会把你的事推到另一个人身上;你要是追问的急了,他?她?接到你的电话就会说在开会,或者在出差,总之这群人就是能推就推,能...

  • 废弃物和垃圾回收机

        在21世纪中,垃圾在不断增多,无数块土地被垃圾污染,无数条河流被垃圾染黑,人们的浪费行为越来越多,让地球,人类的母亲,默默地流下眼泪……    地球的资源是有限的,人们的浪费行为,总有一天会把地球的资源掏空。为了节约资源,我想要发明...

  • Java虚拟机垃圾收集算法简介

    一标记-清除算法(Mark-Sweep)首先标记出所有需要回收的对象,标记完成后统一回收。主要缺点:1.标记和清除效率都很低2.产生大量不连续的内存碎片,导致后面分配大内存空间失败二复制算法将可用内存划分为大小相等的两块,每次只使用其中一块...

  • 林场垃圾回收的工作制度

    为切实做好我场农村“卫生清洁”工程,美化环境,减少污染,提高全场*健康水平,改善广大居民卫生条件,共建林场清洁优美生态环境,特制定本垃圾管理及清运制度。一、各居民点分别设置分类垃圾筒和沤肥窖,各干部职工家中应配备专用的“两桶一袋”,实行垃...