虚拟机---4.gc

下文纯个人理解,有不同意见欢迎指点批评。这些纯个人知识梳理总结

讲到虚拟机,大伙肯定会讲垃圾回收。方便,自动。

那什么是垃圾?没人用了。

那哪里才有垃圾?内存。具体回收都说是堆,其实还有共享方法区;共享方法区,就是放了二进制文件的对象和二进制结构和静态常量的地方;它怎么回收确定,想下,这个二进制文件进来,是有触发。既然回收就是全部触发都没了。new的对象回收了。没有实例了。class对象没人用了。相关静态的信息没人调用。基本就可以撤了。

堆:

那虚拟机怎么知道哪些是垃圾?第一个问题说没人用。那它怎么知道没人用。原始社会是引用计数算法,现在是gcroot算法(可以达到当前);

计数算法,即某对象每给引用一次,即加一;引用不用了,失效了,即减一;问题来了,A引用B,B引用A;

    private class A{
        B b;
        private void setB(B b) {
            this.b = b;
        }
    }
    private class B{
        A a;
        private void setA(A a) {
            this.a = a;
        }
    }
    public static void main(String[] args) {
        A a =new test().new A();
        B b = new test().new B();
        b.setA(a);
        a.setB(b);
        b = null;
        a = null;
        System.gc();

堆里面还互相引用。没完没了。宣布淘汰。

gc roots 算法(可达性)

由头开始相下引用。串起来就成一条链;倘若头没了。就断了。还是用楼上的代码。都给置null。头断了。没用了全回收。

那什么才可以确定为root。这么牛逼。

new的,方法区静态引用,本地方法调用的,方法栈的引用;

知道了哪些是垃圾哪些不是垃圾,那又怎么回收比较好?

先说回收方法有好几种,

比如标记复制,内存分成两部分,把标记用的复制到另一边

标记压缩,标记有用的,往一边靠拢存储

根据堆里面对象存活的生命周期,对象的生命周期很长的很少。很短的很多。

虚拟机搞了个分代回收。把堆分成了eden区,survival1区,survival2区,old区

eden区,新生区,对象new就进来这里new。tlab,线程本地化,每个线程进来2048字节空间用于创建实例。不够再拓展;这里的对象存活时间短。经常需要回收。基本满了。就进行一次回收。叫做minorgc;经常做。采用的是标记复制。复制到幸存区。

survival区,直接保持一个为空,采用标记复制。把没用的,干掉。对象gc次数超过2的4次方次就升级到下一区。

old区,采用的是标记整理。这里的整理是major gc;old区也有引用其他新的区。那就用卡表标识引用。

full gc是全堆垃圾回收,耗时很长。尽量避免,会引起卡顿。

什么时候full gc,old不够了。持久的不够了。

那gc一个垃圾实例又是具体做了啥代码?

其中一步就是调用了我们object里面的finalize方法。且仅仅调用一次。如果垃圾回收,调用方法,方法重写由把该实例激活。那就不再调这个方法。

知道了怎么区分垃圾跟回收的算法,那什么时候区分垃圾跟回收。计算机一直忙个不停。分分钟就又改变了状态。虚拟机采用了stop the world和安全点;

怎么说呢。stop the world就是此app进程内的线程全部暂停,中断。进行算法区分垃圾;这就引发出来不同的垃圾收集器;

安全点,也就是不在有堆创建,堆引用。什么时候呢?本地方法调用,不涉及java代码。长时间执行的指令,比如循环等。都有可能成为安全点。

猜你喜欢

转载自blog.csdn.net/huangddy/article/details/84310416