• JVM---GC垃圾回收总


    目录

    1、JVM的内存模型

    2、如何判断对象是否可以回收(垃圾判断算法)

    3、垃圾回收算法

    4、Java中的四种引用

    5、造成内存溢出的常见原因

    6、JVM堆内存垃圾回收

    7、什么是STW?为什么gc要STW(Stop The World)?

    8、GC 相关参数


    1、JVM的内存模型

            根据虚拟机规范,JVM的内存分为 堆、虚拟机栈、本地方法栈、程序计数器、方法区。

            JDK 1.8 同 JDK 1.7 比,最大的差别就是:元空间取代了永久代。元空间的本质和永久代类似,都是对 JVM 规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。

             虚拟机的内存中主要有程序计数器、虚拟机栈、本地方法栈、堆和方法区。

    什么是永久代和元空间?

            方法区是一种规范,不同的虚拟机厂商可以基于规范做出不同的实现,永久代和元空间就是出于不同jdk版本的实现。

            说白了,方法区就像是一个接口,永久代与元空间分别是两个不同的实现类而已。只不过永久代是这个接口最初的实现类,后来这个接口一直进行变更,直到最后彻底废弃这个实现类,由新实现类——元空间进行替代。

            从上图中可以看到,永久代与堆中的老年代是连续的,这里的连续指的是物理地址连续,永久代本身并不在堆中。因此,老年代与永久代其中一个满了,都会触发Full GC。

            由于方法区主要存储类的相关信息,所以对于动态生成类的情况比较容易出现永久代的内存溢出。最典型的场景就是,在 jsp 页面比较多的情况,容易出现永久代内存溢出,会报出"java.lang.OutOfMemoryError: PermGen space "异常。

            元空间(Metaspace),不再与堆连续,而是直接存在于本地内存中,也就是机器的内存。理论上机器内存有多大,元空间的野心就有多大。

    Java8中,使用元空间替换永久代的原因:
            在之前的版本中,字符串常量池存在于永久代中,在大量使用字符串的情况下,非常容易出现OOM的异常。此外,JVM加载的class的总数,方法的大小等都很难确定,因此对永久代大小的指定难以确定。太小的永久代容易导致永久代内存溢出,太大的永久代则容易导致虚拟机内存紧张。

    2、如何判断对象是否可以回收(垃圾判断算法)

            引用计数法:一个对象被其它变量所引用,计数+1。如果某一个变量不再引用它了,计数-1。                             当计数为0时可以被回收。

            存在问题:如果发生循环引用,如下图。A、B两个对象都不会被回收,计数都为1。

            可达性分析算法 :首先会确定一系列的根对象(GC Root),按照从上至下的方式搜索被根对象集                                  合所连接的目标对象是否可达,如果该对象被跟对象直接或间接的引用,就                                    不能被回收,否则就会被回收。该算法可以有效地解决在引用计数算法中循                                     环引用的问题,防止内存泄漏的发生。

            哪些对象可以作为GC Root:

                                   虚拟机栈中引用的对象:各个线程被调用的方法中使用到的参数、局部变量等。

                                    本地方法栈内 JNI(通常说的本地方法)引用的对象

                                    方法区中类静态属性引用的对象 比如:Java类的引用类型静态变量

                                    方法区中常量引用的对象 比如:字符串常量池(string Table)里的引用

                                    所有被同步锁 synchronized 持有的对象

                                    Java虚拟机内部的引用。

     3、垃圾回收算法

            1、标记-清除算法(Mark-Sweep)

             优点:速度快

            缺点:内存碎片化严重,后续可能发生大对象不能找到可利用空间的问题,会造成内存溢出。

            2、标记-整理算法(Mark-Compact)

                标记后不是清理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象。

            优点:没有内存碎片

            缺点:速度慢、内存开销大 

           3、复制算法(Copying)

                 按内存容量将内存划分为等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉。

             优点:速度快、不会有内存碎片

             缺点:占用双倍空间

    4、Java中的四种引用

            强引用:强引用j就是我们常见的普通引用对象,我们程序中几乎所有的引用使用的都是强引                         用。只要还有一个强引用指向一个对象,就表明该对象还活着,不能被回收

            软引用:一个软引用中的对象,不会很快被JVM回收,当JVM内存不足时,才会对其进行回收

            弱引用:比软引用拥有更短的生命周期。在垃圾回收时,只要发现弱引用,不管堆空间是否                         足够,都会将对象进行回收。由于垃圾回收器是一个优先级很低的线程,因此不一定                      很快发现那些只具有弱引用的对象。

            虚引用:虚引用 就是形同虚设它并不能决定 对象的生命周期。任何时候这个只有虚引用的对                        象都有可能被回收。因此,虚引用主要用来跟踪对象的回收,清理被销毁对象的相关                      资源。

    5、造成内存溢出的常见原因

            StackOverFlowError
            解释:线程栈内存溢出,
            原因:方法递归调用

            OutOfMemoryError:Java heap memory
            解释:堆内存溢出
            原因:大量对象创建撑爆堆区

            OutOfMemoryError:Metaspace
            解释:方法区溢出
            原因:大量类被加载

    6、JVM堆内存垃圾回收

    Java 的自动内存管理主要是针对对象内存的回收对象内存的分配。同时,Java 自动内存管理最核心的功能是 堆 内存中对象的分配与回收。

            堆中存放我们new出来的对象,存放的区域就是Eden区域,但这个区域存满以后就会做minor gc,首先通过可达性分析算法来判断是否是垃圾,如果能够找到引用就不是垃圾,找不到就是垃圾,minor gc过程中我们有一部分是垃圾一部分不是垃圾,会将这些垃圾对象清除,然后非垃圾对象会放到survivor区域的to中并且将对象的分代年龄+1,分代年龄(用来区分对象生命周期的一种标识,比如parallel默认对象分代年龄达到15岁就放到老年代中)。此时一次minor gc结束。我们可以推断出,老年代做full gc的频率应该远远小于年轻代minor gc,老年代等到存放对象快满的时候会做full gc,扫描老年代中的对象是否是垃圾,如果都不是并且此时还有对象要进入老年代,那此时就会报OOM(内存溢出错误)。

            新生代使用的复制算法,老年代使用的是标记整理算法。

    7、什么是STW?为什么gc要STW(Stop The World)?

            指的是GC事件发生过程中,会产生应用程序的停顿。停顿产生时整个应用程序线程都会被暂停,没有任何响应, 有点像卡死的感觉,这个停顿称为STW。可达性分析算法中枚举根节点(GC Roots)会导致所有Java执行线程停顿。

            原因很简单,因为java进行垃圾回收时使用可达性分析,从GC Root向下判断对象是否有引用,如果不把所有线程进入safe points并阻塞起来就会出现对象上一秒没有引用被删除,后一秒又出现引用,导致错误的产生。

    8、GC 相关参数

            

            

  • 相关阅读:
    JS 采用JSON.parse实现深拷贝时出现的问题?
    2022年第十三届蓝桥杯大赛湖南中医药大学第2场选拔赛(部分总结)
    FVP和Juno平台的Memory Layout介绍
    windows server安装mysql后公司区域网连接
    quartz笔记
    选择同步云盘工具?这些值得一试的优秀选择!
    肽核酸如何保存|包含偶氮苯单元的肽核酸(N-PNA)|99Tcm标记c-myc mRNA
    Java语言知识大盘点(期末总复习)一
    专利申请流程详解
    Verilog HDL阻塞赋值和非阻塞赋值笔记
  • 原文地址:https://blog.csdn.net/m0_46979453/article/details/126414356