JVM——GC垃圾回收机制的八个重要面试问题你知道了吗?

GC是干什么的

C语言特点,相当于是一个手动挡的汽车,挂挡比较麻烦,但是能做到更精确的控制
Java语言,相当于是一个自动挡的汽车,开起来更方便,不能像手动车那样精准控制、

内存管理:
C语言中的内存,申请之后,需要手动释放(free/delete)一旦忘记释放,就容易导致“内存泄漏”
在这里插入图片描述

Java中的内存,申请之后,不需要手动释放(GC)
没有垃圾回收,需要程序主动归还内存(取决于用户的素质),有了垃圾回收,相当于有了一个专门负责的人

为什么要有GC

内存申请的时机很好确定,但是释放时机是不好确定的。
比如从一个地方借到一个桌子,你可能要用来举办活动、上课。。。等等,你不确定最后那个桌子是否还需要用,就容易忘记还要还桌子。有一个GC就是相当于有一个人专门管理回收。

为什么C/C++中不引入GC

引入GC会有额外代价
1、需要消耗的资源
2、GC回收内存没有手动释放更及时,用完立刻手动释放,GC还要兼顾到其他资源。
3、GC会影响到正常的程序工作(影响到程序的执行效率STW(Stop the world)问题)

GC要回收哪些内存


主要回收

方法区(类对象)
GC需要回收方法区的内存,但是方法区空间小,数据失去作用的概率低


不需要回收.栈上的内存何时释放时机是明确的. (线程结束,栈上的内存就全部被释放了,某个栈帧销毁(对应方法执行完就销毁),也会导致对应的局部变量被释放)

程序计数器
只是存了一个地址,不需要回收、

回收的基本单位

内存的单位是"字节",回收内存就而是按照对象的方式来回收.
每个对象,都持有了一定的内存.释放对应的对象,也就回收了对应的内存.
在这里插入图片描述

回收对象的基本思路

就类似于有人租书,书店老板需要一个人去收书拿回来,老板就会提供一份租书的名单,这个名单上面就是需要被回收,收书的人按照名单进行回收。
书店老板的判定依据:这本书的租期是否到了.
JVM中的判定依据:这个对象是否会被继续使用.

1、标记:找出这个对象是否需要回收(判段对象的生死)

a)引用计数法(Java中没有,python、php中有)
记录当前这个对象是否有引用指向(有几个引用)

每个对象都专门分配一个计数器变量. 有新的引用指向该对象,引用计数+ 1,有旧的引用指向别的对象了,就引用计数- 1
当引用为0表示该对象没有引用了. (没有引用也就无法在代码中被使用)于是这个对象就可以被回收了

在这里插入图片描述

引用计数法有一个致命缺陷:无法解决循环引用的问题

在这里插入图片描述

b)可达性分析(Java中存在)
遍历这个对象关系的图(有向图),如果某个对象可以被遍历到,就不是垃圾(可达的).如果无法被遍历到,就是不可达.
在这里插入图片描述

在此用树举例子


class Node{
    public  int val;
    public Node left;
    public Node right;

    public Node(int val) {
        this.val = val;
    }
}

public class Test3 {
    public static Node build(){
        Node a = new Node(1);
        Node b = new Node(2);
        Node c = new Node(3);
        Node d = new Node(4);
        Node e = new Node(5);
        Node f = new Node(6);
        Node g = new Node(7);

        a.left = b;
        a.right = c;
        b.left = d;
        b.right = e;
        e.left = g;
        c.right = f;
        return a;
    }
    public static void main(String[] args) {
        Node root = build();
        root.right=null;
        
    }
}

在这里插入图片描述
可达性遍历
遍历的起点不是一个而是很多起点.
把每个起点都要进行往下遍历.
以下三种起点统称为GCRoot
1.针对每个线程的每个栈帧的局部变量表(线程有很多,每个线程栈帧也有很多,每个栈帧中也会有多个变量)
2.常量池中引用的对象
3.方法区中静态变量引用的对象.

c)针对方法区对象的回收(类对象)
规则(同时具有三个条件认为该类对象就可以被回收,都是根据可达性分析)
1)该类的所有实例都已经被回收了
2)加载该类的ClassLoader也已经被回收了
3)该类对象没有在代码中被使用了(包括各种静态成员、包括反射)

2、回收:把死了的对象回收回去
a)标记-清除
在这里插入图片描述

b)标记-复制
在这里插入图片描述

c)标记-整理
在这里插入图片描述

分代回收

按照对象的年龄(不是直接使用时间来记录,而是使用对象活过GC轮次来记录的.(GC是按照-定周期来运行)),把堆内存分成新生代老年代
在这里插入图片描述

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值