Java 是如何垃圾回收的?

1,311 total views, 6 views today

Java 内存回收发生在 JVM 的堆区。
当一个对象到 GC Roots 没有任何引用链相连时,则说明这个对象为可回收的对象。当一个对象有引用时,则说明对象可达(还是存活着的对象)。
可以作为 GC Roots 的对象主要有以下几种:

Java 堆区的内存是分代的,一共有 3 个代。

年轻代,老年代,永久代。


年轻代

年轻代上的回收称为 Minor GC 或者 Young GC,回收算法为复制算法。

在年轻代上,内存分配成 1 个 Eden 区和 2 个 Survivor 区,Eden 空间大,Survivor 空间小(比例 8:1:1),2 个 Survivor 中只有一个是用来保存对象,另一个是空的。对象会被分配在 Eden 区,Eden 区满了,就会触发回收算法,即复制算法。Eden 区和 Survivor_1 区中的可达对象(存活对象),会被复制到另一个 Survivor_2 区。然后清空 Eden 区和 Survivor_1 区。下一次 Eden 区再满的时候,就是往 Survivor_1 区复制存活对象,清空 Survivor_2 和 Eden 区。
Eden 区的对象,每经历一次回收,年龄就+1。

老年代

老年代上的回收称之为 Major GC 或者 Full GC,回收算法标记整理算法。

Eden 区的对象,每经历一次回收,年龄就+1,到年龄达到一定程度(默认 15 岁),就会移动到老年代。老年代的对象不容易死掉。回收频率不高。但是每次回收就会占更多的时间。

永久代

永久代默认大小是 64M,其存放了装载的 Class,方法等信息,很难被回收,所以通常是不会回收永久代上的数据,对于那些有很多类的程序,常常需要加大永久代的内存分配,不然容易导致永久代内存用完的错误。(Hibernate,Spring 这类框架往往会生成大量的动态代理类,会占用很多的永久代内存)。

 

注:Java8 中已经没有永久代了,取而代之的是元空间。

《深入理解 java 虚拟机》中有这么一段话:“对于习惯在 Hotspot 虚拟机上做开发的开发者来说,方法区也被称之为” 永久区”, 本质上,两者并不等价,仅仅是因为 Hotspot 虚拟机设计团队选择把 GC 分代收集扩展到方法区,或者说使用永久代来实现方法区的而已”

原创文章,转载请注明出处!http://www.javathings.top/java是如何垃圾回收的?/

About: wusq


发表评论

电子邮件地址不会被公开。 必填项已用*标注