前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 是如何垃圾回收的?

Java 是如何垃圾回收的?

作者头像
水货程序员
修改2018-12-03 09:35:47
5190
修改2018-12-03 09:35:47
举报
文章被收录于专栏:javathingsjavathings

Java 是如何垃圾回收的?

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

代码语言:javascript
复制
(1)栈帧中的本地变量表所引用的对象。
(2)方法区中类静态属性和常量引用的对象。 
(3)本地方法栈中JNI(Native方法)引用的对象。

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

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

年轻代

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

代码语言:javascript
复制
所谓复制算法,将堆分成2个相同的空间A和B,将A空间中的可达对象,全部复制到B空间,然后整体回收A空间。
算法实现简单,但复制成本大,占用空间大。
年轻代上的对象都是新生对象,生存时间短,很容易被回收,用复制算法来回收成本不会高。

在年轻代上,内存分配成 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,回收算法标记整理算法。

代码语言:javascript
复制
整理算法:先从根节点遍历所有可达对象,标记为可达状态,然后垃圾收集器将这些可达对象聚拢在一起,即内存整理一下,
然后把所有不可达的对象全部回收掉,避免产生内存碎片。

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

永久代

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

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

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java 是如何垃圾回收的?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档