面试挂:请说说Java垃圾是怎么回收的?



点击上方关注 “终端研发部

设为“星标”,和你一起掌握更多数据库知识

作者丨开源中国

https://www.oschina.net/translate/java-gc


什么是自动垃圾回收?


自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将后者删掉的机制。所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象;而未使用中的对象(未引用对象),则没有被任何指针给指向,因此占用的内存也可以被回收掉。


在用 C 之类的编程语言时,程序员需要自己手动分配和释放内存。而 Java 不一样,它有垃圾回收器,释放内存由回收器负责。本文接下来将介绍垃圾回收机制的基本过程。


第一步:标记


垃圾回收的第一步是标记。垃圾回收器此时会找出哪些内存在使用中,还有哪些不是。



上图中,蓝色表示已引用对象,橙色表示未引用对象。垃圾回收器要检查完所有的对象,才能知道哪些有被引用,哪些没。如果系统里所有的对象都要检查,那这一步可能会相当耗时间。


第二部:清除


这一步会删掉标记出的未引用对象。



内存分配器会保留指向可用内存的引用,以供分配新对象。


压缩


为了提升性能,删除了未引用对象后,还可以将剩下的已引用对象放在一起(压缩),这样就能更简单快捷地分配新对象了。



为什么需要分代垃圾收集?


之前说过,逐一标记和压缩 Java 虚拟机里的所有对象非常低效:分配的对象越多,垃圾回收需时就越久。不过,根据统计,大部分的对象,其实用没多久就不用了。


来看个例子吧。(下图中,竖轴代表已分配的字节,而横轴代表程序运行时间)



上图可见,存活(没被释放)的对象随运行时间越来越少。而图中左侧的那些峰值,也表明了大部分对象其实都挺短命的。


JVM 分代


根据之前的规律,就可以用来提升 JVM 的效率了。方法是,把堆分成几个部分(就是所谓的分代),分别是新生代、老年代,以及永生代。



新对象会被分配在新生代内存。一旦新生代内存满了,就会开始对死掉的对象,进行所谓的小型垃圾回收过程。一片新生代内存里,死掉的越多,回收过程就越快;至于那些还活着的对象,此时就会老化,并最终老到进入老年代内存。


Stop the World 事件 —— 小型垃圾回收属于一种叫 "Stop the World" 的事件。在这种事件发生时,所有的程序线程都要暂停,直到事件完成(比如这里就是完成了所有回收工作)为止。


老年代用来保存长时间存活的对象。通常,设置一个阈值,当达到该年龄时,年轻代对象会被移动到老年代。最终老年代也会被回收。这个事件成为 Major GC。


Major GC 也会触发STW(Stop the World)。通常,Major GC会慢很多,因为它涉及到所有存活对象。所以,对于响应性的应用程序,应该尽量避免Major GC。还要注意,Major GC的STW的时长受年老代垃圾回收器类型的影响。


永久代包含JVM用于描述应用程序中类和方法的元数据。永久代是由JVM在运行时根据应用程序使用的类来填充的。此外,Java SE类库和方法也存储在这里。


如果JVM发现某些类不再需要,并且其他类可能需要空间,则这些类可能会被回收。


世代垃圾回收过程


现在你已经理解为什么堆被分成不同的代,现在是时候看看这些空间是如何相互影响的。后面的图片将介绍 JVM 中的对象分配和老化的过程。


首先,所有的新对象分配给 eden 空间,两个 survivor 空间都是空的。


(ps:对象优先在 eden 区中分配,目前主流的垃圾收集器会采用分代回收算法,因此需要将堆内存分为新生代和老年代。


在新生代中为了防止内存碎片问题,因此垃圾收集器一般选用 复制 算法,所以堆内存的新生代又被分为 eden 区 + survivor 1区 + survivor2 区。)



当 eden 空间填满时,则会触发一次小的垃圾收集。



引用的对象移动到第一个 survivor 空间,清除 eden 空间时,将删除未引用的对象。



在下一次Minor GC中,Eden区也会做同样的操作。删除未被引用的对象,并将被引用的对象移动到Survivor区。然而,这里,他们被移动到了第二个Survivor区(S1)。此外,第一个Survivor区(S0)中,在上一次Minor GC幸存的对象,会增加年龄,并被移动到S1中。待所有幸存对象都被移动到S1后,S0和Eden区都会被清空。注意,Survivor区中有了不同年龄的对象。



在下一次Minor GC中,会重复同样的操作。不过,这一次Survivor区会交换。被引用的对象移动到S0,。幸存的对象增加年龄。Eden区和S1被清空。



此幻灯片演示了 promotion。在较小的GC之后,当老化的物体达到一定的年龄阈值(在该示例中为8)时,它们从年轻一代晋升到老一代。



随着较小的GC持续发生,物体将继续被推广到老一代空间。



所以这几乎涵盖了年轻一代的整个过程。最终,将主要对老一代进行GC,清理并最终压缩该空间。


如喜欢本文,请点击右上角,把文章分享到朋友圈
如有想了解学习的技术点,请留言给若飞安排分享

最后说一句(别白嫖,求关注)


回复 【idea激活】即可获得idea的激活方式

回复 【Java】获取java相关的视频教程和资料

回复 【SpringCloud】获取SpringCloud相关多的学习资料

回复 【python】获取全套0基础Python知识手册

回复 【2020】获取2020java相关面试题教程

回复 【加群】即可加入终端研发部相关的技术交流群

阅读更多

用 Spring 的 BeanUtils 前,建议你先了解这几个坑!

lazy-mock ,一个生成后端模拟数据的懒人工具

在华为鸿蒙 OS 上尝鲜,我的第一个“hello world”,起飞!

字节跳动一面:i++ 是线程安全的吗?

一条 SQL 引发的事故,同事直接被开除!!

太扎心!排查阿里云 ECS 的 CPU 居然达100%

一款vue编写的功能强大的swagger-ui,有点秀(附开源地址)

相信自己,没有做不到的,只有想不到的

在这里获得的不仅仅是技术!


喜欢就给个“在看

相关推荐

  • 腊月27日凌晨的一个紧急 Elasticsearch 线上问题复盘
  • 面试官:说一下 GET 和 POST 最本质的区别?
  • SpringBoot巧用 @Async 提升API接口并发能力
  • 谷歌裁员细节曝光:开源主管被裁,61岁程序员在线求职,有人60天找不到工作就被遣返
  • 最好的SpringBoot系统!!!
  • 使用 fcntl 模块对文件进行加解锁
  • ChatGPT全景图 | 产品+商业篇
  • 别总写代码,这130个网站比涨工资都重要!
  • 一男医生乱发女患者私密照;乳山部分海景房每平米跌破千元;韩国女子在驻韩美军基地被性侵;鱼跃医疗被罚270万元...|酷玩日爆
  • 日本啤酒品牌的中国大溃败
  • 美国又要对华为下黑手了,我们怎么办?
  • 《狂飙》证明:影视剧里的坏人,其实教不坏观众
  • 流浪地球周边到!2800+零件还原装甲车,科幻迷沸腾了!
  • 双腿截肢黑人男子遭美警连开10枪身亡;英工人维修核潜艇时用胶水粘螺丝螺栓;美国拟追加20亿美元对乌军援 | 每日大新闻
  • 《流浪地球2》No,《The Wandering Earth II》Yes!外网影评之怪现状
  • 快手精排模型实践
  • 实现高并发秒杀的七种方式
  • 一文走进多核架构下的内存模
  • 天猫汽车商详页的SSR改造实践
  • 聊聊天空计算,跨云存储与Xline