JVM常见的垃圾回收器

1、回收方法区:

        方法区回收价值很低,主要回收废弃的常量和无用的类。

方法区中的存储:
    方法区中存储的是加载的类的信息,常量,静态变量,即时编译后的代码等数据,所以回收的对象也就是这些内容。

何种场景需要回收:
    既然回收方法区不是必须的,虽然效率低下,但是当内存不够使用的时候依然是会抛出OOM的,那么我们需要知道什么场景下需要去回收方法区。首先我们需要弄明白方法区会回收那些对象。在JDK1.7之前,常量池是在方法区中的,在此版本及以后则将其移到堆中。基于目前版本主要是1.8及以上,故我们以1.8为准。在此版本上,主要回收的是无用的类。如何判定一个类是无用的:
 

  • 无用的类回收有以下条件:

        ①JAVA实例已经全部被回收,在堆中没有该类的示例存在;

        ②该类的classLoader被回收;

        ③该类的java.long.class对象没有被引用,不会被其他方法通过反射访问该类的方法

        与堆中的对象回收机制不同,不是不用即回收。HotSpot虚拟机提供了-Xnoclassgc参数进行控制是否回收。
 

2、垃圾回收器:

Serial、Serial Old、PawNew、CMS、Parallel Scavenge、Parallel Old、G1

  • Serial收集器,串行收集器是最古老,最稳定以及效率高的收集器,可能会产生较长的停顿,只使用一个线程去回收。
  • ParNew收集器,ParNew收集器其实就是Serial收集器的多线程版本。
  • Parallel收集器,Parallel Scavenge收集器类似ParNew收集器,Parallel收集器更关注系统的吞吐量。
  • Parallel Old 收集器,Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法
  • CMS收集器,CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。
  • G1收集器,G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征

CMS垃圾收集器
 

CMS(并发标记清除收集器)(Concurrent Mark Sweep) 

        CMS是基于“标记-清除"算法实现的、以最短停顿时间为目标的垃圾收集器,CMS垃圾回收器主要针对老年代进行垃圾回收

        CMS回收垃圾的整个过程分为以下四个阶段:

                即初始标记阶段、并发标记阶段、重新标记阶段 和 并发清除阶段。

                (涉及STW,暂停用户线程的阶段主要是:初始标记 和 重新标记)

        CMS垃圾收集器在并发标记阶段并发清除阶段能让用户线程和GC线程并发执行,因此在整个垃圾收集过程中用户不会感到明显的卡顿:

  •         初始标记(Initial-Mark)阶段: 初始标记阶段会暂停所有的用户线程, 单线程标记与GC Roots直接关联的对象, 单线程标记是为了确保标记过程的准确性和一致性。这个阶段的主要任务仅仅只是标记出与GCRoots能直接关联到的对象。一旦标记完成之后就会立即进入并发标记阶段,恢复之前被暂停的所有用户线程。此外,由于与GC Roots直接关联对象比较少,所以初始标记阶段的速度非常快。
  •         并发标记(Concurrent-Mark)阶段:在并发标记阶段中,程序的工作线程会和垃圾回收线程并发执行或者交叉执行,垃圾回收线程会进行可达性分析,会从GC Roots直接关联的对象开始向下遍历堆中的对象图,标记所有可达的对象 。这个过程耗时较长但是不需要停顿用户线程。
  •         重新标记(Remark)阶段:由于工作线程在并发标记阶段可能会造成对象的引用发生变化,即原本可达的对象变成了垃圾对象,不可达对象变成了可达对象,所以重新标记阶段垃圾回收器会暂停所有工作线程,对在并发标记阶段中发生变化的对象进行重新标记、修正
    • 注意只能修正原有对象不能修正新增对象,即只能修正原有对象非可达变可达、可达变非可达。
  •         并发清除(Concurrent-Sweep)阶段:清理在标记阶段判断已经死亡的对象,释放内存空间。由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的

CMS缺点:

  1. 内存碎片问题:CMS 使用的是标记-清除算法,它会在回收垃圾对象之后产生大量的内存碎片。当老年代空间碎片太多时,如果无法找到一块足够大的连续内存存放对象时,将不得不提前触发一次Full GC。 

  2. 无法处理浮动垃圾:并发标记阶段用户线程可能会产生新对象,重新标记阶段只能修正原有对象非可达变可达、可达变非可达,不能新增,那么这些新增对象有可能在并发标记和并发清理阶段变为浮动垃圾对象,CMS 无法直接处理这些浮动垃圾,需要等到下一次 GC 才能回收。

  3. 并发标记引起的CPU资源紧张:在并发标记阶段,用户线程与垃圾回收线程并发执行,这可能会增加一定程度的 CPU 消耗

  4. 回收时要确保用户线程有足够内存:不能等老年代满了再回收,而是老年代内存到达某个阈值后回收,防止用户线程在并发执行过程中新创建对象导致内存不够,导致虚拟机补偿使用Serial Old收集器进行回收并处理内存碎片,从而浪费更多时间。默认情况下,当老年代使用了92%的空间后就会触发CMS垃圾回收机制。可以通过-XX:CMSInitiatingOccupancyFraction来设置 

  • 优点:
    • 并发速度快;
    • 低停顿:仅初始标记和重新标记阶段需要停顿用户线程,这两个阶段运行速度很快,CMS垃圾收集器在并发标记阶段并发清除阶段能让用户线程和GC线程并发执行,因此在整个垃圾收集过程中用户不会感到明显的卡顿。

演示非可达变为可达:

        在 main 方法中,首先创建了一个对象 obj,并将其设置为 null,使其成为不可达状态。然后,在后续代码中,通过 new 关键字重新创建了一个 MyClass 对象,并将其赋值给 obj,使得 obj 变为了可达状态。在这个过程中,就实现了非可达变可达的情况。

public class NonReachableToReachableExample {
    
    static class MyClass {
        // 类中的成员变量
        int data;
        
        // 类的构造函数
        MyClass(int data) {
            this.data = data;
        }
    }

    public static void main(String[] args) {
        // 创建一个 MyClass 对象并赋值给变量 obj,初始时它是不可达的
        MyClass obj = null;
        
        // 在并发标记阶段后,某个用户线程重新获取了对 obj 的引用,使得 obj 变为可达
        obj = new MyClass(10);
        
        // 在重新标记阶段,obj 被标记为可达
        // 在此之前,obj 是不可达的,但由于用户线程的活动,它变为了可达
        // 因此,在重新标记阶段需要修正这个状态
    }
}

G1垃圾回收器:

        G1(Garbage-First,垃圾优先收集器):

  •         G1垃圾回收器不再把堆划分为连续的分代,而是将堆内存分割成2048个大小相等的Region,各Region根据需要扮演伊甸园区、幸存区、老年代区、巨大区Humongous Region。垃圾优先收集器跟踪各Region里垃圾的回收价值(回收空间大小和预计回收时长),在后台维护一个优先级列表,每次根据用户设定允许的收集停顿时间,回收优先级最高的那些Region,以达到垃圾优先的效果。
  • 设置最大停顿时间:-XX:MaxGCPauseMillis=默认0.2s
  •          G1从整体来看是基于标记-整理算法实现的回收器,但从局部(两个Region之间)上看又是基于复制算法实现的。
  •         G1在JDK9之后成为了默认的垃圾回收器,取代了Parallel Scavenge 、Parallel Old默认组合,而CMS被声明为不推荐使用的垃圾回收器。  

步骤:

  •         初始标记:初始标记阶段会暂停所有的用户线程, 单线程标记与GC Roots直接关联的对象, 单线程标记是为了确保标记过程的准确性和一致性。这个阶段的主要任务仅仅只是标记出与GCRoots能直接关联到的对象。
  •         并发标记:在并发标记阶段中,程序的工作线程会和垃圾回收线程并发执行或者交叉执行,垃圾回收线程会进行可达性分析,从GC Roots直接关联的对象开始向下遍历堆中的对象图,标记所有可达的对象 。这个过程耗时较长但是不需要停顿用户线程。
  •         最终标记:重新标记所有存活的对象和上个阶段用户线程新产生的可达对象。并发停顿。采用SATB算法,效率比CMS重新标记高。并发停顿。
  •         筛选回收:根据优先级列表,回收价值高的一些Region,将存活对象通过标记复制算法复制到同类型的空闲Region。根据指定的最大停顿时间回收,因此可能来不及回收所有垃圾对象,但能保证回收到最高回收价值的垃圾。并发停顿。

初始标记阶段会暂停所有的用户线程, 单线程标记与GC Roots直接关联的对象, 单线程标记是为了确保标记过程的准确性和一致性。这个阶段的主要任务仅仅只是标记出与GCRoots能直接关联到的对象。一旦标记完成之后就会立即进入并发标记阶段,恢复之前被暂停的所有用户线程。此外,由于与GC Roots直接关联对象比较少,所以初始标记阶段的速度非常快。

Minor GC与Full GC分别在什么时候发生?

        新生代内存不够用时候发生MGC也叫YGC,JVM内存不够的时候发生FGC

引用的分类:

        强引用:GC时不会被回收

        软引用:描述有用但不是必须的对象,在发生内存溢出异常之前被回收

        弱引用:描述有用但不是必须的对象,在下一次GC时被回收

        虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,用PhantomReference实现虚引用,虚引用用来在GC时返回一个通知。
 

 你知道哪些JVM性能调优:

设定堆内存大小

-Xmx:堆内存最大限制。

设定新生代大小。 新生代不宜太小,否则会有大量对象涌入老年代

-XX:NewSize:新生代大小

-XX:NewRatio 新生代和老生代占比

-XX:SurvivorRatio:伊甸园空间和幸存者空间的占比

设定垃圾回收器 年轻代用 -XX:+UseParNewGC 年老代用-XX:+UseConcMarkSweepGC

JVM的永久代中会发生垃圾回收么?

        垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确的永久代大小对避免Full GC是非常重要的原因。请参考下Java8:从永久代到元数据区 (注:Java8中已经移除了永久代,新加了一个叫做元数据区的native内存区)

类的生命周期:
     

   类的生命周期包括这几个部分,加载、连接、初始化、使用和卸载,其中前三部是类的加载的过程,如下图:

加载,查找并加载类的二进制数据,在Java堆中也创建一个java.lang.Class类的对象

连接,连接又包含三块内容:验证、准备、初始化。 1)验证,文件格式、元数据、字节码、符号引用验证; 2)准备,为类的静态变量分配内存,并将其初始化为默认值; 3)解析,把类中的符号引用转换为直接引用

初始化,为类的静态变量赋予正确的初始值

使用,new出对象程序中使用

卸载,执行垃圾回收
 

 Java对象创建过程

1.JVM遇到一条新建对象的指令时首先去检查这个指令的参数是否能在常量池中定义到一个类的符号引用。然后加载这个类(类加载过程在后边讲)

2.为对象分配内存。一种办法“指针碰撞”、一种办法“空闲列表”,最终常用的办法“本地线程缓冲分配(TLAB)”

3.将除对象头外的对象内存空间初始化为0

4.对对象头进行必要设置
 

对象分配规则:

        对象优先分配在Eden区,如果Eden区没有足够的空间时,虚拟机执行一次Minor GC。

        大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)。这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)。

        长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄计数器,如果对象经过了1次Minor GC那么对象会进入Survivor区,之后每经过一次Minor GC那么对象的年龄加1,知道达到阀值对象进入老年区。

        动态判断对象的年龄。如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代。

        空间分配担保。每次进行Minor GC时,JVM会计算Survivor区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次Full GC,如果小于检查HandlePromotionFailure设置,如果true则只进行Monitor GC,如果false则进行Full GC。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/563204.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

go+react实现远程vCenter虚拟机管理终端

文章目录 React-VcenterDemoQuick Start React-Vcenter 基于go & react实现远程vSphere vcenter虚拟机终端console页面,提供与vcenter管理中的Launch Web Console相同的功能。 项目地址:react-vcenter Demo URL: http://localhost:3000 Quick St…

【leetcode面试经典150题】66. 分隔链表(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主,题解使用C语言。(若有使用其他语言的同学也可了解题解思路,本质上语法内容一致&…

第24天:安全开发-PHP应用文件管理模块显示上传黑白名单类型过滤访问控制

第二十四天 一、PHP文件管理-显示&上传功能实现 如果被抓包抓到数据包,并修改Content-Type内容 则也可以绕过筛查 正常进行上传和下载 二、文件上传-$_FILES&过滤机制实现 无过滤机制 黑名单过滤机制 使用 explode 函数通过点号分割文件名,…

基于Java+SpringBoot+Mybaties-plus+Vue+elememt 小区物业管理系统 的设计与实现

一.项目介绍 系统分为管理员 和 业主 两块: 管理员点击进入到系统操作界面,可以对首页、业主信息管理、管理员信息管理、 楼栋和房屋信息管理、物业费管理、地下停车位管理、公告信息管理、报修信息管理、 投诉管理以及个人信息等功能模块 …

温湿度LCD显示并上传服务器

项目需求 通过温湿度传感器将值传到LCD1602,并实时通过蓝牙透传到手机。 硬件介绍 温湿度传感器 DHT11温湿度传感器 DHT11_温湿度传感器数据格式-CSDN博客 LCD1602LCD1602-CSDN博客 HC-01 继电器模块 硬件接线 LCD1602 D0~D7 --> A0~A7VDD, A --> 5v…

MercadoLibre(美客多)入仓预约系统操作流程-自动化约号(开篇)

目录 一、添加货件信息 二、输入货件信息 三、选择发货 四、填写交货日期 五、注意事项 MercadoLibre(美客多)于2021年10月18号上线了新预约入仓系统,在MercadoLibre美客多平台上,新入仓预约系统是一项非常重要的功能&#x…

23种设计模式之抽象工厂

简单工厂和工厂方法 关注 产品等级 抽象工厂 关注 产品族 对于比较稳定的产品,抽象工厂更有效率(一个工厂生产很多产品族) 抽象工厂代码例子加深理解

探索UWB模块的潜力:智能家居与物联网的连接者

UWB模块具有精准定位、快速响应、低能耗等特点,在智能家居领域展现出了巨大的潜力,正逐渐成为智能家居与物联网的重要连接者。本文将探讨UWB模块在智能家居与物联网中的关键作用、应用场景以及未来发展趋势,旨在为推动智能家居技术的创新和发…

Springboot的Test单元测试操作

Springboot的Test单元测试操作 简单总结需要操作的步骤 1&#xff0c;导入依赖 2&#xff0c;创建目录&#xff08;目录和启动类的目录保持一致&#xff09; 3&#xff0c;添加注解 4&#xff0c;写方法测试 1&#xff0c;导入依赖 <dependency><groupId>org.spri…

C++修炼之路之多态---多态的原理(虚函数表)

目录 一&#xff1a;多态的原理 1.虚函数表 2.原理分析 3.对于虚表存在哪里的探讨 4.对于是不是所有的虚函数都要存进虚函数表的探讨 二&#xff1a;多继承中的虚函数表 三&#xff1a;常见的问答题 接下来的日子会顺顺利利&#xff0c;万事胜意&#xff0c;生活明朗--…

(51单片机)第十一章-串行口应用提高

11.1 方式0应用 在第6章中&#xff0c;已经对51单片机的串行口结构做过详细介绍&#xff0c;并且通过实例讲解了串行口的4种工作方式中方式1的具体用法&#xff0c;本节详细讲述串行口方式0的用法。 串行口方式0被称为同步移位寄存器的输入/输出方式&#xff0c;主要用于扩展并…

PCDN与边缘计算的集成解决方案

PCDN与边缘计算的集成解决方案 在数字化时代&#xff0c;内容的快速、安全地传递至用户变得至关重要。无论是媒体、教育还是其他领域&#xff0c;所有这些行业都需要强大的技术支持以保证信息的实时更新和安全传输。PCDN&#xff08;Peer Content Delivery Network&#xff0c…

详解QListView、QListWidget、QTableView、QTableWidget的使用以及区别

在Qt框架中&#xff0c;QListView、QListWidget、QTableView和QTableWidget都是用于显示列表或表格数据的控件。它们在用途、数据模型、灵活性以及直接操作数据的便捷性等方面存在一定的差异。下面将详细阐述这些控件的使用方法以及它们之间的区别&#xff0c;并提供相应的C代码…

YAML教程-2-Python读写YAML文件

领取资料&#xff0c;咨询答疑&#xff0c;请➕wei: June__Go 上一小节我们讲解了一下YAML文件的基本使用方法&#xff0c;本小节我们学习一下Python读写YAML文件的方法。 在Python中读写YAML文件&#xff0c;通常会使用PyYAML这个第三方库&#xff0c;因为它提供了与YAML格…

前后端交互概念

前后端交互概念 1前后端分离开发概念2搭建后端环境2.1配置文件commomcommon-utilservice-utilmodelservice gitee使用 1前后端分离开发概念 前段&#xff1a;运用html、css、js和现成库&#xff0c;对数据作展示。 后端&#xff1a;运用Java和Java框架&#xff0c;提供数据或操…

数据结构10:堆和堆排序

文章目录 树的概念及结构树的概念树的相关概念树的表示树在实际中的应用表示文件系统的目录树结构 二叉树概念及结构概念特殊的二叉树二叉树的性质二叉树的存储结构顺序存储链式存储 二叉树的顺序结构及实现二叉树的顺序结构堆的概念及结构 堆的实现堆的插入堆的删除堆的创建向…

C# winfrom 超详细UI创建过程 实现双色球选号器UI界面设计过程

一、 效果展示 1. 无点击效果展示&#xff1a;不选中——双色球为灰色&#xff0c;字体也为灰色 2.点击双色器效果展示&#xff1a;选中——双色球为红或者蓝&#xff0c;字体为白色 二、 使用控件标注说明 三、界面特点介绍 双色球代码控制生成---------由于红色33个球&…

上位机工作感想-从C#到Qt的转变-1

0.前言 接触Qt开发也有一年多的时间了&#xff0c;还记得去年初从杭州回合肥时&#xff0c;刚来公司面临的几个问题&#xff1a; 1.C#转上位机的迷茫2.新公司管理模式的差异3.试用期的各种紧急任务。 当时也是加班加点学习C和Qt的基础知识&#xff0c;做了两个考核项目后&am…

生态短讯 | Tapdata 与 TDengine 完成产品兼容性互认证,打造物联网实时数据生态

近月&#xff0c;深圳钛铂数据有限公司&#xff08;以下简称钛铂数据&#xff09;自主研发的实时数据平台&#xff08;Tapdata Live Data Platform&#xff09;与北京涛思数据科技有限公司&#xff08;以下简称涛思数据&#xff09;自主研发的大数据平台 TDengine&#xff0c;已…

arm版Linux下安装大数据集群各种组件

背景&#xff1a;由于本人是用的Macbookpro m2来进行开发的&#xff0c;很多环境和Intel芯片的都不一样&#xff0c;期间安装各种软件遇到各种问题&#xff0c;为了以后不走之前的老路&#xff0c;现记录各种软件的安装步骤。 系统安装组件说明 序号组件名称组件版本1jdkjdk-…