JVM之垃圾回收器

1.如何判断对象可以回收

1.1 引用计数法

什么是引用计数器法

在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的。

缺点:无法解决对象之间循环引用的问题。例如,当二个对象相互引用时,并且这二个对象也不可能再被访问,那么这二个对象将永远存在于内存当中不会被回收。

 引用计数器算法有一些比较著名的应用案例,但是Java虚拟机并没有采用这种算法。

1.2 可达性分析算法

1.什么是可达性分析算法

可达性分析算法是通过一系列称为"GC Roots"的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为"引用链",如果某个对象到GC Roots间没有任何引用链相连,则证明此对象是不可能被使用的。

2.可以作为 GC Roots 的对象

  • 在虚拟机栈(栈帧中的本地变量表)中引用的对象。例如当前正在运行的方法所用到的参数、局部变量、临时变量等。
  • 在方法区中类静态属性引用的对象,例如Java类的引用类型静态变量
  • 在方法区中常量引用的对象,例如字符串常量池里的引用
  • 在本地方法栈中JNI(即通常所说的Native方法)引用的对象
  • Java虚拟机内部的引用,如基本数据类型对应的Class对象、一些常驻的异常对象(比如NullPointException、OutOfMemoryError等)、系统类加载器等
  • 所有被同步锁(synchronized关键字)持有的对象
  • 反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。

除了上述这些固定的GC Roots集合以外,根据用户所选用的垃圾收集器以及当前回收的内存区域不同,还可以有其它对象临时性的加入,共同构成完整的GC Roots集合。例如后面会提到的分代收集和局部回收,如果只针对Java堆中某一块区域发起垃圾收集(例如只针对新生代的垃圾收集),而这个区域的对象完全有可能被位于堆中其他区域的对象所引用,这时候就需要将这些关联区域的对象一并加入GC Roots集合中。

3.四种引用

强引用:

  • 强引用是程序代码中普遍存在的引用赋值,即类似"Object obj = new Object()"这种引用关系。无论任何情况下,只要GC Roots与对象之间存在强引用关系,那么垃圾回收器就永远不会回收这个对象。

软引用:

  • 软引用是用来描述一些还有用但非必须的对象。只被软引用关联着的对象,在系统将要发出内存溢出异常前,会把这个对象列进回收范围之中进行第二次回收,如果第二次回收之后还没有足够的内存,才会抛出内存溢出异常。JDK提供了SoftReference类来实现软引用。
  • 可以配合引用队列来释放软引用自身

弱引用:

  • 仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象。JDK提供了WeakReference类来实现弱引用。
  • 可以配合引用队列来释放弱引用自身

虚引用:

  • 虚引用是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间造成影响,也无法通过虚引用来获取一个对象实例,为一个对象设置虚引用的唯一目的只是为了能在这个对象被垃圾收集器回收时收到一个系统通知。JDK提供了PhantomReference类来实现虚引用。
  • 必须配合引用队列使用,主要配合 ByteBuffer 使用,被引用对象回收时,会将虚引用入队, 由 Reference Handler 线程调用虚引用相关方法释放直接内存

注意

1.上述前四种引用的引用强度从上到下依次减弱

2.除上述四种引用外,还有一种无须手动编码的引用,称为终结器引用

终结器引用:无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由 Finalizer 线程通过终结器引用找到被引用对象并调用它的 finalize 方法,第二次 GC 时才能回收被引用对象

2.垃圾回收算法

2.1 分代收集

1.分代收集理论

        当前商业虚拟机的垃圾收集器,大多数都遵循了分代收集的理论进行设计,分代收集名为理论,实质上是一套符合大多数程序运行实际情况的经验法则,它建立在二个分代假说之上:

弱分代假说:绝大多数对象是朝生夕灭的

强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡

        这二个分代假说奠定了多款常用的垃圾收集器的一致的设计原则:收集器应该将Java堆划分出不同的区域,然后将回收对象依据其年龄(年龄即对象熬过垃圾收集过程的次数)分配到不同的区域之中存储。显而易见,如果一个区域中大多数对象都是朝生夕灭,难以熬过垃圾收集过程的话,那么把它们集中放在一起,每次回收时只关注如何保留少量存活而不是去标记那些大量将要被回收的对象,就能以较低代价回收到大量的空间;如果剩下的都是难以消亡的对象,那把它们集中放在一块,虚拟机便可以使用较低的频率来回收这个区域。

        把分代收集理论放到现在的商用Java虚拟机里,设计者一般至少会把Java堆划分为新生代和老年代二个区域。顾名思义,新生代中,每次垃圾回收都有大批对象死去,而每次回收后存活的少量对象,将会逐步晋升到老年代中存放。针对新生代或老年代或整个堆的收集则有如下不同的名词:

部分收集

  • 新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集
  • 老年代收集(Major GC/Old GC):指目标只是老年代的收集。目前只有CMS收集器会有单独收集老年代的行为。
  • 混合收集:指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。

整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集

注意

1.但是对象之间很可能是存在跨代引用的。例如,新生代中的对象有可能被老年代中的对象所引用,具体解决方法见<<深入理解Java虚拟机>>

2.在HotSpot中,新生代内存不足,会触发Minor GC,使用新生代垃圾回收器完成垃圾回收;老年代内存不足,会触发Full GC,使用新生代垃圾回收器完成新生代的垃圾回收,使用老年代垃圾回收器完成老年代的垃圾回收

2.HotSpot的分代垃圾回收

对象首先分配在伊甸园区域

新生代空间不足时,触发 minor gc,伊甸园和 from 存活的对象使用 copy 复制到 to 中,存活的对象年龄加 1 并且将幸存区的 from 和 to 交换

minor gc 会引发 stop the world,暂停其它用户的线程,等垃圾回收结束,用户线程才恢复运行

当对象寿命超过阈值时,会晋升至老年代,最大寿命是15(4bit)

当老年代空间不足,会先尝试触发 minor gc,如果之后空间仍不足,那么触发 full gc,STW的时 间更长

2.2 标记清除

什么是标记清除

        标记清除算法分为标记和清除两个阶段:首先需要标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象,也可以反过来,标记存活的对象,统一回收所有未被标记的对象。

优点:

  • 相比于标记整理算法速度更快

缺点:

  • 标记和清除二个过程的执行效率会随对象数量增长的效率而降低
  • 会造成内存碎片

2.3 标记整理算法

什么是标记整理算法

        首先标记出所有需要回收的对象,也可以反过来,标记存活的对象,然后让所有存活的对象向内存空间一端移动,最后直接清理掉边界以外的内存,

优点

不会产生内存碎片

缺点

相比于垃圾清除算法速度慢

2.4 标记复制算法

什么是标记复制算法

        它将可用内存按容量划分为大小相等的二块,每次只使用其中的一块。当这一块的内存用完了,就将还活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

优点

不会有内存碎片

缺点

需要占用双倍内存空间

        现在的商用Java虚拟机优先采用了这种收集算法去回收新生代。但是,IBM曾有一项研究对新生代的朝生夕死的特点做了一个更量化的诠释:新生代中的对象有98%熬不过第一轮收集。因此,并不需要1:1的比例划分新生代的内存空间

2.5 JVM的相关参数

3.垃圾回收器

3.1 垃圾回收器概述

什么是垃圾回收器

        垃圾收集算法是内存回收的方法论,而垃圾回收器是内存回收的实践者。《Java虚拟机规范》中对垃圾收集器如何实现并没有做出任何规定,因此不同厂商、不同版本的虚拟机所包含的垃圾回收器都可能会有很大差别,不同的虚拟机一般也会提供各种参数供用户根据自己的应用特点和要求组合出各个内存分代所使用的收集器。

垃圾回收器的分类

1. 串行

  • 单线程
  • 堆内存较小,适合个人电脑

2. 吞吐量优先

  • 多线程
  • 堆内存较大,多核 cpu
  • 让单位时间内,STW 的时间最短,垃圾回收时间占比最低,这样就称吞吐量高

3. 响应时间优先

  • 多线程
  • 堆内存较大,多核 cpu 尽可能让单次 STW 的时间最短

不同垃圾回收器的组合

        上图展示了七种作用于不同分代的垃圾回收器,如果二个回收器之间存在连线,这说明它们可以搭配使用,但这个关系不是一成不变的,在JDK的一些版本中,某些组合已经被废弃了。

        直到目前还没有最好的垃圾回收器,跟更加不存在万能的垃圾回收器,我们应选择对具体的应用最合适的垃圾回收器。

3.2 串行的垃圾回收器

开启串行垃圾回收器的JVM参数

-XX:+UseSerialGC = Serial + SerialOld

Serial和SerialOld是二种串行的垃圾回收器。其中:

Serial:是一种单线程的垃圾回收器,用于新生代,采用标记复制算法进行垃圾回收。

SerialOld:是一种单线程的垃圾回收器,用于老年代,采用标记整理算法进行垃圾回收。

3.3 吞吐量优先的垃圾回收器

开启吞吐量优先的垃圾回收器

-XX:+UseParallelGC ~ -XX:+UseParallelOldGC

Parallel和ParallelOld是二种吞吐量优先的垃圾回收器。其中:

Parallel:是一款多线程并行收集的垃圾回收器,用于新生代,采用标记复制算法

ParallelOld:是一款多线程并行收集的垃圾回收器,用于老年代,采用标记整理算法

开启其它参数

//动态调整伊甸园和幸存区的比例、整个堆的大小、晋升阈值的大小
-XX:+UseAdaptiveSizePolicy
//下面这二个参数开启后,Parallel和ParallelOld会尝试达到对应的目标
//吞吐量的目标
-XX:GCTimeRatio=ratio
//最大暂停毫秒数的目标,默认200ms
-XX:MaxGCPauseMillis=ms
//控制线程数
-XX:ParallelGCThreads=n    

3.4 响应时间优先的垃圾回收器

开启响应时间优先的垃圾回收器

-XX:+UseConcMarkSweepGC ~ -XX:+UseParNewGC ~ SerialOld

CMS 和 ParNew 是二种响应时间优先的垃圾回收器。其中:

CMS:是一款多线程的垃圾回收器,进行垃圾回收的过程中涉及到并行和并发,用于老年代,采用标记清除算法。另外,CMS进行垃圾回收时可能会造成内存碎片过多,当新生代垃圾回收内存不足时,老年代由于内存碎片太多,也内存不足,这种情况下,会采用SerialOld进行老年代的垃圾回收

ParNew:是一款多线程并行收集的垃圾回收器,用于新生代,采用标记复制算法

//参数1:并行的线程数,默认是4、参数2:并发的线程数,建议设置为并行线程数的四分之一
-XX:ParallelGCThreads=n ~ -XX:ConcGCThreads=threads
//当老年代内存占比达到percent时,执行CMS,这么做的目的是预留一些空间给浮动垃圾用
-XX:CMSInitiatingOccupancyFraction=percent
//新生代对象有可能引用老年代的对象,但某些引用了老年代对象的新生代对象,本身是要作为垃圾处理的,
所以通过打开此开关,在进行重新标记之前,先针对新生代进行一次垃圾回收,这样做就减少了重新标记的
压力
-XX:+CMSScavengeBeforeRemark

3.5 G1垃圾回收器

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

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

相关文章

芯旺微冲刺IPO,车规级MCU竞争白热化下的“隐忧”凸显

在汽车智能化和电动化发展带来的巨大蓝海市场下&#xff0c;产业链企业迎来了一波IPO小高潮。 日前&#xff0c;上海芯旺微电子技术股份有限公司&#xff08;以下简称“芯旺微”&#xff09;在科创板的上市申请已经被上交所受理&#xff0c;拟募资17亿元&#xff0c;用于投建车…

【如何提高在浏览器时的专注力!去广告和新闻!】如何使用浏览器时看不到任何新闻以及广告【浏览器去除广告和新闻】

如何使用浏览器时看不到任何新闻以及广告 1. 使用chrome浏览器或者其他浏览器都可以2. 使用bing搜索3. 去广告 1. 使用chrome浏览器或者其他浏览器都可以 2. 使用bing搜索 bing 3. 去广告

【bug】记录一次使用Swiper插件时loop属性和slidersPerView属性冲突问题

简言 最近在vue3使用swiper时&#xff0c;突然发现loop属性和slides-per-view属性同时存在启用时&#xff0c;loop生效&#xff0c;下一步只能生效一次的bug&#xff0c;上一步却是好的。非常滴奇怪。 解决过程 分析属性是否使用错误。 loop是循环模式&#xff0c;布尔型。 …

Qt展示动态波形

Qt展示动态波形 需求描述成品展示实现难点Qt多线程 需求描述 接入串口&#xff0c;配置串口顺序进行接收数据&#xff1b;数据分成两个串口分别传入&#xff0c;使用多线程并发接入&#xff1b;时域数据有两个通道&#xff08;I&#xff0c;Q&#xff09;&#xff0c;分别以实…

【汇总】解决Ajax请求后端接口,返回ModelAndView页面不跳转

【汇总】解决Ajax请求后端接口&#xff0c;返回ModelAndView不跳转 问题发现问题解决方法一&#xff1a;直接跳转到指定URL&#xff08;推荐&#xff09;方法二&#xff1a;将返回的html内容&#xff0c;插入到页面某个元素中方法三&#xff1a;操作文档流方法四&#xff1a;使…

Windows terminal 添加 git bash 解决git中文乱码显示问题

Windows terminal 添加 git bash 解决git中文乱码显示问题 在 windows terminal 中配置git 说明&#xff1a; 点击箭头选择设置 说明&#xff1a; 点击"添加新配置文件"配置名称命令行&#xff0c;可执行文件的具体语句 C:\Program Files\Git\bin\bash.exe启动目录…

什么是注意力机制?注意力机制的计算规则

我们观察事物时&#xff0c;之所以能够快速判断一种事物(当然允许判断是错误的)&#xff0c;是因为我们大脑能够很快把注意力放在事物最具有辨识度的部分从而作出判断&#xff0c;而并非是从头到尾的观察一遍事物后&#xff0c;才能有判断结果&#xff0c;正是基于这样的理论&a…

【C语言】初阶结构体

&#x1f388;个人主页&#xff1a;库库的里昂 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;C语言初阶 ✨其他专栏&#xff1a;代码小游戏 &#x1f91d;希望作者的文章能对你有所帮助&#xff0c;有不足的地方请在评论…

P14 电路定理——巧妙-灵性-智慧

1、替代定理 图示表示&#xff1a; 叠加定理和齐性定理只能用于线性电路&#xff0c;但是替代定理无论线不线性都可以用。 常见的&#xff1a;线性电路将某复杂支路等效成电压源或电流源之后&#xff0c;就可以使用叠加原理了。 引入两个相互抵消的电压源&#xff0c;拿其中一…

基于STM32设计的智能空调

一、项目背景 随着人们生活水平的不断提高&#xff0c;对居住环境的舒适度要求也越来越高。空调作为一种重要的家电设备&#xff0c;已经成为了现代家庭中必不可少的一部分。本文介绍了一种基于STM32的智能空调设计方案&#xff0c;可以自动地根据环境温度进行温度调节。 二、…

Opencv-C++笔记 (15) : 像素重映射 与 图像扭曲

文章目录 一、重映射简介二、图像扭曲 一、重映射简介 重映射&#xff0c;就是把一幅图像中某位置的像素放置到另一图像指定位置的过程。即&#xff1a; 在重映射过程中&#xff0c;图像的大小也可以同时发生改变。此时像素与像素之间的关系就不是一一对应关系&#xff0c;因…

PHP从入门到精通—PHP开发入门-PHP概述、PHP开发环境搭建、PHP开发环境搭建、第一个PHP程序、PHP开发流程

每开始学习一门语言&#xff0c;都要了解这门语言和进行开发环境的搭建。同样&#xff0c;学生开始PHP学习之前&#xff0c;首先要了解这门语言的历史、语言优势等内容以及了解开发环境的搭建。 PHP概述 认识PHP PHP最初是由Rasmus Lerdorf于1994年为了维护个人网页而编写的一…

租赁类小程序定制开发|租赁管理系统源码|免押租赁系统开发

随着互联网的发展&#xff0c;小程序成为了一种重要的移动应用开发方式。租赁小程序作为其中的一种类型&#xff0c;可以为很多行业提供便利和创新。下面我们将介绍一些适合开发租赁小程序的行业。   房屋租赁行业&#xff1a;租房小程序可以帮助房东和租户快速找到合适的租赁…

对当下AI的一些观感思考

目前来看&#xff0c;AI技术地震的震中还是在美帝那旮瘩。尤其是M7&#xff0c;这几家市值加总快15万亿美元了&#xff0c;个个都是行业翘楚&#xff0c;个个都有拿得出手的东西。AI是个技术密集、人才密集、计算密集的产业。美帝拥有全球一流的顶尖人才&#xff0c;以及财力、…

IntelliJ IDEA 2023.2社区版插件汇总

参考插件帝&#xff1a;https://gitee.com/zhengqingya/java-developer-document 突发小技巧&#xff1a;使用插件时要注意插件的版本兼容性&#xff0c;并根据自己的实际需求选择合适的插件。同时&#xff0c;不要过度依赖插件&#xff0c;保持简洁和高效的开发环境才是最重要…

2023下半年软考初级程序员报名入口-报名流程-备考方法

软考初级程序员2023下半年考试时间&#xff1a; 2023年下半年软考初级程序员的考试时间为11月4日、5日。考试时间在全国各地一致&#xff0c;建议考生提前备考。共分两科&#xff0c;第一科基础知识考试具体时间为9:00到11:30&#xff1b;第二科应用技术考试具体时间为2:00到4…

STM32 低功耗-睡眠模式

STM32 睡眠模式 文章目录 STM32 睡眠模式第1章 低功耗模式简介第2章 睡眠模式简介2.1 进入睡眠模式2.1 退出睡眠模式 第3章 睡眠模式代码示例总结 第1章 低功耗模式简介 在 STM32 的正常工作中&#xff0c;具有四种工作模式&#xff1a;运行、睡眠、停止和待机模式。 在系统或…

小白到运维工程师自学之路 第六十四集 (dockerfile构建tomcat、mysql、lnmp、redis镜像)

一、tomcat&#xff08;更换jdk&#xff09; mkdir tomcat cd tomcat/ tar xf jdk-8u191-linux-x64.tar.gz tar xf apache-tomcat-8.5.40.tar.gzvim Dockerfile FROM centos:7 MAINTAINER Crushlinux <syh163.com> ADD jdk1.8.0_191 /usr/local/java ENV JAVA_HOME /us…

AcWing257. 关押罪犯(二分图+染色法)

输入样例&#xff1a; 4 6 1 4 2534 2 3 3512 1 2 28351 1 3 6618 2 4 1805 3 4 12884输出样例&#xff1a; 3512 解析&#xff1a; 二分&#xff0c;每次查看是否是二分图 #include<bits/stdc.h> using namespace std; typedef long long ll; const int N2e45,M2e55…

《Spring Boot源码解读与原理分析》书籍推荐

Spring Boot 1.0.0 早在2014年就已经发布&#xff0c;只不过到了提倡“降本增效”的今天&#xff0c;Spring Boot才引起了越来越多企业的关注。Spring Boot是目前Java EE开发中颇受欢迎的框架之一。依托于底层Spring Framework的基础支撑&#xff0c;以及完善强大的特性设计&am…