首页 > 其他分享 >9 JVM垃圾回收

9 JVM垃圾回收

时间:2024-03-05 15:57:14浏览次数:21  
标签:对象 内存 回收 算法 GC 垃圾 JVM 引用

9 JVM垃圾回收

方法区的回收

方法区中能回收的内容主要就是不再使用的类。判定一个类可以被回收,需要同时满足下面三个条件:

  • 1.此类所有实例对象都已经被回收,在堆中不存在任何该类的实例对象以及子类对象
  • 2.加载该类的类加载器已经被回收
  • 3.该类对应的java.lang.Class对象没有在任何地方被引用

手动触发垃圾回收

如果需要手动触发垃圾回收,可以调用System.gc()方法
注意事项:

  • 调用System.gc()方法并不一定会立即回收垃圾,仅仅是向Java虚拟机发送一个垃圾回收的请求,具体是否需要执行垃圾回收Java虚拟机会自行判断。

堆内存的回收

堆内存中对象没有被引用才可以回收,如何判断堆上的对象有没有被引用?有两种方法:引用计数法、可达性分析

引用计数法

引用计数法会为每个对象维护一个引用计数器,当对象被引用时加1,取消引用时减1

引用计数法缺点

  • 每次引用和取消引用都需要维护计数器,对系统性能会有一定的影响
  • 存在循环引用问题,所谓循环引用就是当A引用B,B同时引用A时会出现对象无法回收的问题

可达性分析算法

Java使用的是可达性分析算法来判断对象是否可以被回收。可达性分析将对象分为两类: 垃圾回收的根对象(GCRoot) 和普通对象,对象与对象之间存在引用关系。下图中A到B再到C和D,形成了一个引用链,可达性分析算法指的是如果从某个到GC Root对象是可达的,对象就不可被回收

哪些对象被称之为GCRoot对象

  • 线程Thread对象
  • 系统类加载器加载的java.lang.Class对象
  • 监视器对象,用来保存同步锁synchronized关键字持有的对象
  • 本地方法调用时使用的全局对象

几种常见的对象引用

可达性算法中描述的对象引用,一般指的是强引用即GCRoot对象对普通对象有引用关系,只要这层关系存在普通对象就不会被回收。除了强引用之外,Java中还设计了几种其他引用方式:

  • 软引用

    软引用相对于强引用是一种比较弱的引用关系,如果一个对象只有软引用关联到它,就会将软当程序内存不足时,引用中的数据进行回收

    在JDK 1.2版之后提供了SoftReference类来实现软引用,软引用常用于缓存中

    软引用的执行过程如下:

    1.将对象使用软引用包装起来,new SoftReference<对象类型>(对象)

    2.内存不足时,虚拟机尝试进行垃圾回收

    3.如果垃圾回收仍不能解决内存不足的问题,回收软引用中的对象

    4.如果依然内存不足,抛出OutOfMemory异常

    byete[] bytes = new byte[1024 * 1024 * 100];
    SoftReference<byte[]> softReference = new SoftReference<byte[]>(bytes);
    
  • 弱引用

    • 弱引用的整体机制和软引用基本一致,区别在于弱引用包含的对象在垃圾回收时,不管内存够不够都会直接被回收

    • 在JDK 1.2版之后提供了WeakReference类来实现弱引用,弱引用主要在ThreadLocal中使用。弱引用对象本身也可以使用引用队列进行回收

  • 虚引用

    • 虚引用和终结器引用这两种引用在常规开发中是不会使用的

    • 虑引用也叫幽灵引用/幻影引用,不能通过虚引用对象获取到包含的对象。虚引用唯一的用途是当对象被垃圾回收器回收时可以接收到对应的通知。Java中使用PhantomReference实现了虚引用,直接内存中为了及时知道直接内存对象不再使用,从而回收内存,使用了虚引用来实现。

  • 终结器引用

    • 终结器引用指的是在对象需要被回收时,终结器引用会关联对象并放置在Finalizer类中的引用队列中,在稍后由一条由FinalizerThread线程从队列中获取对象,然后执行对象的finalize方法,在对象第二次被回收时,该对象才真正的被回收。在这个过程中可以在finalize方法中再将自身对象使用强引用关联上,但是不建议这样做

垃圾回收算法

常见的垃圾回收算法有四种:标记-清除算法、复制算法、标记-整理算法、分代GC

标记-清除算法

标记清除算法的核心思想分为两个阶段:

  1. 标记阶段将所有存活的对象进行标记。Java中使用可达性分析算法,从GC Root开始通过引用链遍历出所有存活对象
  2. 清除阶段从内存中删除没有被标记也就是非存活对象

优点:实现简单,只需要在第一阶段给每个对象维护标志位,第二阶段删除对象即可

缺点

  1. 碎片化问题
    由于内存是连续的,所以在对象被删除之后,内存中会出现很多细小的可用内存单元。如果我们需要的是一个比较大的空间,很有可能这些内存单元的大小过小无法进行分配

  2. 分配速度慢

    由于内存碎片的存在,需要维护一个空闲链表,极有可能发生每次需要遍历到链表的最后才能获得合适的内存空间

复制算法

复制算法的核心思想是:

  1. 准备两块空间From空间和To空间,每次在对象分配阶段,只能使用其中一块空间(From空间)
  2. 在垃圾回收GC阶段,将From中存活的对象复制到To空间,即将没有被回收的对象复制到To空间
  3. 将From和To空间的名字进行互换,对象存放的空间永远都叫From空间

优点

  1. 吞吐量高,复制算法只需要遍历一次存活对象复制到To空间即可,比标记-整理算法少了一次遍历的过程,因而性能较好,但是不如标记-清除算法因为标记清除算法不需要进行对象的移动
  2. 不会发生碎片化,复制算法在复制之后就会将对象按顺序放入To空间中,所以对象以外的区域都是可用空间,不存在碎片化内存空间

缺点

  1. 内存使用率低,每次只能让一半的内存空间来创建对象使用

标记整理算法

核心思想分为两个阶段:

  1. 标记阶段,将所有存活的对象进行标记。Java中使用可达性分析算法,从GC Root开始通过引用链遍历出所有存活对象
  2. 整理阶段,将存活对象移动到堆的一端。清理掉存活对象的内存空间

优点

  1. 内存使用效率高,整个堆内存都可以使用,不会像复制算法只能使用半个堆内存
  2. 不会发生碎片化,在整理阶段可以将对象往内存的一侧进行移动,剩下的空间都是可以分配对象的有效空间

缺点

  1. 整理阶段的效率不高,整理算法有很多种,比如Lisp2整理算法需要对整个堆中的对象搜索3次,整体性能不佳。可以通过Two-Finger、表格算法、ImmixGC等高效的整理算法优化此阶段的性能

分代GC算法

现代优秀的垃圾回收算法,会将上述描述的垃圾回收算法组合进行使用,其中应用最广的就是分代垃圾回收算法(Generational GC)。

分代垃圾回收将整个内存区域划分为年轻代(存放存活时间比较短的对象,年轻代里面包括伊甸园区(Eden),还有两块幸存者区(Survivor),这两块幸存者区使用标记-整理算法)和老年代(存活对象时间比较长的对象):

  1. 分代回收时,创建出来的对象,首先会被放入Eden伊甸园区
  2. 随着对象在Eden区越来越多,如果Eden区满,新创建的对象已经无法放入,就会触发年轻代的GC,称为Minor GC或者Young GC
  3. Minor GC会把需要Eden中和From需要回收的对象回收,把没有回收的对象放入To区
  4. 如果Minor GC后对象的年龄达到闻值(最大15,默认值和垃圾回收器有关),对象就会被晋升至老年代。当老年代中空间不足,无法放入新的对象时,先尝试Minor GC,如果还是不足,就会触发Full GC,Full GC会对整个堆进行垃圾回收。如果Full GC依然无法回收掉老年代的情况,那么当对象继续放入老年代时,就会抛出Out Of Memory异常

判断GC算法是否优秀,可以从三个方面来考虑

  • 吞吐量
    吞吐量指的是CPU 用于执行用户代码的时间与 CPU 总执行时间的比值,即吞吐量 = 执行用户代码时间/(执行用户代码时间 + GC时间)。吞吐量数值越高,垃圾回收的效率就越高

  • 最大暂停时间

    最大暂停时间指的是所有在垃圾回收过程中的STW(stop the world)时间最大值。最大暂停时间越短,用户使用系统时受到的影响就越短。

  • 堆使用效率

    不同垃圾回收算法,对堆内存的使用方式是不同的。比如标记清除算法,可以使用完整的堆内存。而复制算法会将堆内存一分为二,每次只能使用一半内存。从堆使用效率上来说,标记清除算法要优于复制算法。

上述三种评价标准:一般来说堆使用效率、吞吐量,以及最大暂停时间不可兼得,堆内存越大,最大暂停时间就越长。想要减少最大暂停时间,就会降低吞吐量。不同的垃圾回收算法,适用于不同的场景

标签:对象,内存,回收,算法,GC,垃圾,JVM,引用
From: https://www.cnblogs.com/miaoyindian/p/18054216

相关文章

  • P1156 垃圾陷阱
    原题链接题解太妙了如果能出去,那么出去的时间一定为让我出去的那个垃圾掉落的时间,且在此之前我所在的高度能撑到我垃圾掉落如果出不去,我肯定一直呆在井底不动所以我们可以以高度为变量设每个高度能撑到的最久的时间而每个垃圾在拿到的一瞬间要么吃要么搭,所以我们穷举,两个都......
  • AI智能分析网关V4智慧环保/智慧垃圾站视频智能分析与监控方案
    一、背景介绍随着城市化进程的加速,垃圾处理问题日益受到人们的关注,传统的垃圾站管理方式已经无法满足现代社会的需求。针对当前垃圾站的监管需求,TSINGSEE青犀可基于旗下视频智能检测AI智能分析网关V4与安防监控视频综合管理系统EasyCVR平台,打造智慧垃圾站视频监控与智能分析方案......
  • 内存与垃圾回收篇之(四)程序计数器
    程序计数器(PC寄存器)1.PCRegister介绍​ JVM中的程序计数寄存器(ProgramCounterRegister)中,Register的命名源于CPU的寄存器,寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能够运行。​ 这里,并非是广义上所指的物理寄存器,或许将其翻译为PC计数器(或指令计数......
  • 内存与垃圾回收篇之(三)运行时数据区概述及线程
    运行时数据区概述及线程1.概述经过类加载器子系统之后,方法区中就保存了运行时类本身。​ 内存是非常重要的系统资源,是硬盘和CPU的中间仓库及桥梁,承载着操作系统和应用程序的实时运行。JVM内存布局规定了Java在运行过程中内存申请、分配、管理的策略,保证了JVM的高效稳定运行。......
  • 内存与垃圾回收篇之(二)类加载器子系统
    类加载器子系统1.内存结构概述如果自己手写一个Java虚拟机的话,主要考虑哪些结构呢?类加载器和执行引擎2.类的加载器及类加载过程2.1类加载器子系统的作用类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识。ClassLoader只负责c......
  • 内存与垃圾回收篇之(一)JVM与Java体系结构
    JVM与Java体系结构1.前言JVM拥有当前最前沿、最成熟的垃圾回收算法JIT:即时编译器AOT:提前编译器JVM:代码托管技术拓展:前端编译器:负责把Java文件编译成Class文件,如Sun的Javac;后端运行期编译器(JIT编译器):负责把Class文件的字节码转换成机器码,如HotSpot的C1,C2编译器;静态提前......
  • JVM常用
    JVM包含多种不同类型的参数选项-D用来设置系统属性,属于标准选项-X设置非标准选项,支持的选项范围跟具体的JVM实现有关-XX设置高级选项,允许开发者调整JVM的行为、性能、输出调试信息,支持的选项范围也跟具体的JVM实现有关布尔类型的高级选项是起到功能的开关作用,不带参数。......
  • 容器化环境中,JVM最佳参数配置实践
    本文分享自华为云社区《Java应用容器化参数配置最佳实践》,作者:可以交个朋友。简介当你在物理机或者虚拟机上配置JVM参数时,JVM会默认使用主机上1/4的内存作为堆内存,你也可以选择使用-Xmx/-Xms来指定Java堆内存大小。在容器化环境中,每个容器实例的内存大小由Cgroups配置决定,......
  • 如果正确清理docker可用回收资源
    正确清理Docker可用回收资源必须条件docker.service正常运行执行dockersystemprune,如下<root@DEV-K8S-WN4~>#dockersystempruneWARNING!Thiswillremove:-allstoppedcontainers-allnetworksnotusedbyatleastonecontainer-alldanglingimage......
  • 垃圾分类新篇章:大屏引领,共筑环保未来
    在当下社会,垃圾分类已成为我们日常生活中不可或缺的一部分。随着环保意识的逐渐增强,如何高效、准确地进行垃圾分类成为了摆在我们面前的重要课题。而垃圾分类管理大屏作为一种创新的管理工具,正逐渐走进我们的生活,助力我们共同构建绿色、和谐的居住环境。 垃圾分类管理大屏,集数......