JVM面试题:垃圾回收

1、为什么要有垃圾回收?

在传统的 C/C++ 语言中,开发人员需要手动分配和释放内存,这样就容易导致人为的忘记释放内存的情况,造成内存泄漏。Java 的垃圾回收机制可以把帮忙解决这个问题,它可以自动检测并回收不再使用的对象,也就是垃圾,可以减少内存泄漏的风险。

2、Java 垃圾回收中是如何判断一个对象死亡的?请简单介绍一下

常用的算法有两个,也就是 “引用计数算法” 和 “可达性分析法”。

  • 引用计数法的思路很简单,当对象被引用时给计数器 + 1,当对象引用失效时计数器值 – 1。当计数器为零时,说明对象不再被使用,可以回收。
  • 可达性分析法的思路就是从 GC Roots 开始向下搜索,当对象到 GC Roots 都没有任何引用相连时,说明对象是不可用的,可以被回收。其中 GC Roots 是一组必须活跃的引用,从 GC Roots 出发,程序通过直接引用或间接引用,能够找到可能正在被使用的对象。

3、刚才说到了引用计数法,引用计数法存在什么问题?

引用计数法的缺点是,如果对象存在循环依赖,那就无法定位该对象是否改被回收,比如 A 引用 B,B 引用 A 这种情况。

4、刚才说到了可达性分析,知道哪些可以作为 GCROOT 吗?

比方说 JVM 内存结构中的虚拟机栈,虚拟机栈中有栈帧,栈帧里面存储着有指向堆的对象引用,那么位于虚拟机栈顶的栈帧就可以称作是 “活跃” 的栈帧,因为此刻它正在被线程调用。所以,当前活跃的栈帧指向堆里的对象引用就可以是 GC Roots。除此之外,类的静态变量,Java 本地方法所引用的对象都可以是 GC Roots。

5、垃圾回收算法介绍一下

垃圾回收的第一步是 “标记”,标记那些没有被 GC Roots 引用的对象,也就是垃圾。标记完之后,JVM 就可以选择直接清除那些垃圾,这个算法叫做 “标记清除算法”。

这个过程简单粗暴,但也存在内存碎片问题,导致可能我有 10M 的内存,但程序申请 9M 的空间却会失败,也就是说整个内存空间的 10M 是不连续的。解决的办法就是在标记完垃圾后,不直接清除,而是先把存活的对象都复制到另一块空间,复制完了之后,再把整个原空间给清除掉。这个过程叫做 “标记复制算法”。

这种算法也有缺点:内存利用率很低,得有一块新的内存留作复制。那就不如折中一下,可以在标记之后,把存活的对象移到当前空间的一边,把垃圾移到另一边,然后再清除,就没有内存碎片的问题,同时内存利用率也不会降低。这个过程叫做 “标记整理算法”。

6、垃圾回收会发生在哪几个区域?

垃圾回收主要是发生在堆上,尤其是在新生代中,一次垃圾回收通常可以回收 70% 到 99% 的内存空间。但其实也会对方法区进行垃圾回收。对方法区主要回收的是废弃的常量和不再使用的类,一般回收的空间比较少。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值