美文网首页
JAVA 垃圾回收机制

JAVA 垃圾回收机制

作者: 超人TIGA | 来源:发表于2020-12-17 21:06 被阅读0次

垃圾回收之前,先来了解一下运行时数据是怎么存的。

先来一个最简单的例子。

public class Demo{

    public static void main(String[] args){
        System.out.println("Hello world");
    }
    
    private void methodA(){
        int x = 5;
        int y = 8;
        int z = x + y;
    }

    private void methodB(){
    }
}

这个demo,从运行到结束,都经历了什么流程,里面的数据都怎么处理了?其实,程序代码,都是由一个个线程跑起来的,main方法也不例外,启动一个线程,就会产生一个虚拟机栈。

栈里面放的栈帧,就是方法method,而每一个方法里面都可以定义局部变量(int x = 5;),还可以设置返回值等。大致上如下图: image.png 还有其他的操作数栈,就是用于符合操作的,例如上面的int z = x + y,通过入栈和出栈,得到最终结果。

动态链接,最常见的就是多态。
返回地址,就是一个方法执行完,要返回到哪里继续执行。
要注意,局部变量表存储的是8种基本类型,那对象类型呢?存哪里。

private void methodB(){
    Object o = new Object();
}

其实方法里的对象变量,是存在堆里面的,但是局部变量表会有一个引用,指向堆里面的这个对象。

排除在堆中的对象变量,上面的一系列东西,都是跟随线程的生命周期的,就是线程私有,一个线程有一份,是个线程有十分。

接下来,我们看共享的部分,方法区和堆。这里就是线程共享的东西。这部分的数据,是共享的,跟线程的生命周期无关。
放方法区的数据:字节码、静态变量、常量
放堆的数据:对象

既然这部分的数据跟线程的生命周期无关,也就是说,当线程全部逻辑结束了,方法区和堆里面的数据,也不会立刻被销毁。同时又因为这是共享的数据,如果要销毁回收,一定要先知道还有没有其他地方在使用。而这里就需要了解内存的分代思想了,也就是JMM。

image.png 这就是JMM的内存模型。
方法区:绿色的部分,jdk1.8以前是永久代,1.8以后是元空间,区别是什么呢?其实就是1.8以后,这一部分允许内存空间不连贯了。
堆:2个蓝色的部分,即新生代+老年代,而新生代又分为3个,Eden区和2个交换区S0和S1,他们的大小比例是8:1:1。
存放对象

当我们存放对象的时候,一般会遵循一些规则:
①先存放到Eden区
②如果新对象的大小>Eden区的大小,可以直接存到老年代
③长期存活的对象进入老年代(经历15次垃圾回收)
④担保原则
记住无论经过多少次垃圾回收,都只会在新生代和老年代这里,不会去到永久代或者元空间。元空间存放的是字节码、常量、静态变量的

GC垃圾回收

可达性分析算法:GCRoot(对象)、常量、静态变量
检查引用链,判断对象的存活。
如果对象存活,则不回收。而垃圾回收的过程,就是利用算法,对堆的清理和整理。

复制回收算法
image.png 把内存分为2个区,一个正在使用的,一个预留的,如果触发回收,则把使用区里面的不可回收对象,找出来并逐一放到预留区,然后把使用区擦除清空。(这时候,使用区和预留区就对换了,左边变成了预留区,右边变成了使用区)
优点:简单高效,不会存在内存碎片,典型的空间换时间例子。
缺点:内存利用率低,永远只有一半在使用,当存活的对象越来越多,效率就越来越低。
标记清除算法
image.png 标记清除也很好理解,分2步,标记和清除。
①扫描内存区,把可回收的对象标记
②把标记的对象进行回收
优点:存活对象很多时,效率高
缺点:碎片化,如果再有一个大的对象新建,由于没有足够的连续空间分配,会提前触发GC。
标记整理算法
image.png 标记整理则是:
①把不可回收的对象标记
②把不可回收的对象进行整理,排在内存的一端连续空间内
③调整边界的指针,然后把边界外的空间进行清理
优点:标记清理算法的优化,避免了碎片的产生
缺点:效率会相对慢
那各个区分别用什么回收算法呢?

Minor GC
对新生代进行回收,不影响老年代。用的算法是复制回收算法,因为Eden区的对象,大部分都是生命周期很短的对象,用效率最快的算法。
Full GC
对整个堆进行回收,而其中的老年代和元空间,用的是标记清除和标记整理算法。由于是对整个堆进行回收整理,所以效率肯定相对慢,所以要尽量减少Full GC的次数。

总结

当我们不停地创建对象,就会先放到堆中的Eden区;
①如果Eden满了,就把存活的对象放到s0中;
②Eden和S0都满了,就触发Minor GC,利用复制回收算法,把存活对象整理到S1;
③交换区的S0和S1中的数据,每经历一次回收,计数+1,当经历过15次回收后还是存活,则会把这些对象转移到老年代。
④老年代被写满、主动调用System.gc则会触发Full GC,利用标记清除+标记整理算法进行回收。

另外,如果一开始就用存活的对象,塞满Eden和S0,那就直接全部转到老年代,然后把新生代的空间都回收了。

相关文章

  • Java垃圾回收详解

    深入理解 Java 垃圾回收机制 深入理解 Java 垃圾回收机制 一:垃圾回收机制的意义 java 语言中一个...

  • Java 内存区域和GC机制

    Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与...

  • JVM垃圾回收机制

    JVM垃圾回收 整体思维导图 带着问题理解JVM垃圾回收机制 Java为什么需要垃圾回收机制; 回收哪部分垃圾; ...

  • java内存结构和GC机制

    Java垃圾回收概况 Java GC(Garbage Collection,垃圾回收)机制,是Java与C++/C...

  • 对 Java 内存的一些理解-[Android_YangKe]

    Java 垃圾回收机制优点 Java 内存模型 什么是内存抖动 什么是内存泄漏 垃圾回收机制常见算法 Java 垃...

  • Android知识大纲

    Android知识大纲 Java垃圾回收机制 Java内存是如何划分的,Java语言为什么要使用垃圾回收机制? 垃...

  • 优秀的程序员更重视阅读源码,不看源码那是假的

    从事Java开发的都知道java有个垃圾回收机制Garbage collection,要准确理解Java的垃圾回收...

  • JavaScript垃圾回收机制

    什么是垃圾回收机制? 和java,c#一样,javascript也有垃圾回收的机制,比如说c++和c就没有垃圾回收...

  • 2020-04-19 垃圾回收机制算法

    垃圾回收机制算法 垃圾回收机制概述 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存...

  • JVM之Java垃圾回收机制

    为大家推荐一篇写的通俗易懂的关于Java垃圾回收机制的文章理解Java垃圾回收机制 Java主要把内存分为堆内存和...

网友评论

      本文标题:JAVA 垃圾回收机制

      本文链接:https://www.haomeiwen.com/subject/zihzgktx.html