Java垃圾回收机制

java中的垃圾回收机制(Garbage Collection )可以自动清除在堆中不用的对象,为java程序员提供了方便,在c/c++中,我们就需要手动去释放堆中的内存。

在java中对象都是通过引用来使用的,如果没有引用指向这个对象,那么这个对象就不可到达,我们就没法使用和处理这个对象,GC机制就是释放这些不可达对象所占用的内存。

为了提高效率,JVM优化了GC机制,在不同的情况下采用不同的回收方式。不管采用什么方式,我们首先要搞清楚怎样才能访问到对象,正如在 堆栈总结中说的,对象都是通过引用访问的,而引用都保存在栈中,因此我们可以通过栈来找到那些可以访问的对象。

JVM有两种基本的回收方式,一种是“mark and sweep”,另一种是“copy and sweep”。所谓mark and sweep就是JVM通过栈找到所有可到达对象,并且对它们进行标记,然后扫描整个堆,找到剩余对象,释放剩余对象占用的内存。 对于copy and sweep这种模式,堆被分为两个区域,对象存储在一个区域,另外一个为空区域,JVM从栈出发,找到可到达对象,并复制它们到空白的区域紧密排列,然后清空对象以前所在的区域,从而使它成为新的空白区域。copy and sweep比较复杂,但是在新建对象时,它可以提供一个大块的连续空间。因此如果一个对象存活时间比较长,我们就采用mark and sweep;如果对象经常被改动,我们就采用copy and sweep 模式。

以上这两种模式通过分代回收(generational collection)来混合使用,每个对象都记录了一个它经历过垃圾回收的次数,次数越长,则说明这个对象存活时间越长。

JVM中的堆可以分为三个部分,分别为永久区,年老区,和新生区。在永久区中的对象不会被回收,比如Class对象就放在这里。年老区和新生区要进行垃圾回收。年轻区中存放的时新创建的比较新的对象,年老区存放的经历时间比较久的对象。按照上面的分析,年轻区采用copy and sweep模式,年老区采用mark and sweep模式。

年轻区又分为三个区域,eden区,from区,to区,在eden区存放了上次GC之后新创建的对象。from区和to区的大小相等,相当于copy and sweep中的两个区域,当新创建的对象没法放入eden区时,JVM就用copy and sweep模式,将eden和from区中可到达的对象复制到to区,然后清空eden区和from区,然后让from区变为新的to区,to区变为from区。如果to区放不下,就会把年老的对象放入成熟区,就算to区没有满,JVM也会将年代久远的对象放到年老区。
如果年老区没法加入新的对象,JVM就采用mark and sweep 模式对年老区进行垃圾回收。

你可能感兴趣的:(java,垃圾回收,内存管理)