当前位置: 首页 > news >正文

【JVM】 垃圾回收篇——自问自答(1)

Q什么是垃圾:
运行程序中,没用任何指针指向的对象。


Q为什么需要垃圾回收?
内存只分配,不整理回收,迟早会被消耗完。

内存碎片的整理,为新对象腾出空间

没有GC程序无法正常进行。


Q 哪些区域有GC,哪些区域会有OOM异常(错误)?

堆和方法区是线程共享的,存在GC 和OOM
堆有新生代和养老代,默认比例1:2 ,
新生代分为Eden :s0:s1 默认比例 8:1:1 (实际发现JDK8是6:1:1,一度怀疑是自适应策略,结果不是)
新生代中有YGC/MinorGC, 当Eden区满的时候触发,并使用复制算法,和分代策略,将Eden区和from区的存活对象 放到to区,如果存不下,就直接晋升老年代。
其余对象在对象头的分代阈值为15时晋升到老年代。

老年代垃圾回收为MajorGC,一般是老年代满的时候会被触发。为全堆回收

方法区若发生GC,为FUllGC,此时会对全堆以及方法区进行垃圾回收。

简单一句话:频繁收集年轻代,较少收集老年代,基本不动元空间。

PC寄存器 即没用GC 也没用OOM

虚拟机栈,无GC,有OOM 当栈的大小可以被动态扩容时,申请扩容的大小已经超过了内存可以支配空间,发生OOM,
StackOverFlowError,当栈空间大小是固定的,当前栈帧没有足够空间入栈了,此时方式 SOFERROR


Q:垃圾回收相关算法

标记阶段:引用计数和可达性分析算法。目的:判断对象的存活。


引用计数:
一个对象A,有一个引用计数器。当A被任何一个对象引用了,则A的计数器加1。引用失效,引用计数器则减1。
PS:什么叫A被一个对象引用了?举个例子。

class ReferenceClass{
    //static filed
  public static  A a =new A();
}
对象(new A()),被对象 ReferenceClass的静态变量引用,我们知道类变量的初始化是在类加载三部曲的初始化阶段<clint里>,随着类卸载而消亡。
若ReferenceClass类的生命周期不结束。对象(new A())就会一直被类变量a 引用着。
这里再发散:静态变量在逻辑上是存放在方法区的,从JDK7以后,静态变量和字符串常量池就存放在了堆空间中。

引用计数法有个缺陷:循环引用问题。
注意:java在标记阶段并没有使用引用计数算法。

在分析引用、对象等问题的时候。
一定要注意一个问题,这个引用到底是在方法中(局部变量),还是在类内的成员变量上
因为从内存解构上,局部引用是在虚拟机栈的局部变量表中的,而类内的成员变量引用,是在堆内的。

比如:
class  InstanceA{
    
    //此引用的位置是在对象内存解构中的
    Object ref =null;

    public static void main(String[] args){
        //这个引用,a1,是在局部变量表中的
        Instance a1 =new Instance();
        //这个ref 是在堆中,对象体内的
        a1.ref =a1;
        
        //操作数栈指向堆内对象的指针断开。a1.ref 是在堆内又指向自己。
        a1 =null; 
        
    }

}

Python使用的就是引用计数:解决循环引用的两个方法:
手动解除引用。
使用弱引用。

可达性分析算法:(追踪性垃圾收集)
首先要搞清楚,什么是GC Roots
GC roots 是一组集合,它包括:
1、虚拟机栈中的引用的对象
 比如 各个线程中被调用的方法中使用到的参数,局部变量等
 
2、本地方法栈引用的对象。


3、方法区静态属性引用的引用的对象。如上面的例子,A是引用类型的静态类型变量,它就是一个典型的GC root
class ReferenceClass{
    //static filed
  public static  A a =new A();
}

4、方法区中常量引用对象。
class Demo{

    String s ="abc";
    
    public void foo(){
     String ddd="XXXYYY"; //局部变量表最大slot深度为2,ddd为局部变量表中变量,XXXYYY在常量池中
    }

}

5、所有被同步锁持有的对象 同步监视器

6、java虚拟机内部的引用:
各种常驻对象,比如NUllPointerException,OOM,还有系统类加载器。基本数据类型的Class对象

关于Class对象的内存模型:

7、根据不同的垃圾收集器以及当前回收区域不同,也会有一些临时性的GC roots对象加入。
比如使用G1回收器时,新生代的region里的对象,被老年代的某些对象所引用。此时,老年代的引用,就是临时的GC Roots
即指向某一堆内存中的对象的引用(指针),其本身与被引用对象不在一个回收的逻辑区内,它就是GC roots

为了保证GC roots的准确性,就需要在可达性分析时,内存是一个快照状态,而非运行时。保证其一致性。
此时就会产生STW stop the world。

   补问:Q 对象的finalization机制

对象终止机制:系统进行垃圾回收之前,会调用该对象的finalize()方法。
该方法是Object类所有,允许被子类所重写。用于在对象回收时进行资源释放,清理等操作。

但是注意,不要主动去调用某个对象的finalize方法,而是交给垃圾回收机制去调用(GC的finalizer守护线程)。

对象可能有三种状态:
可触及的:从根节点开始,可以到达这个对象
可复活的:无引用的对象,可以在 finalize()中复活。
不可触及的:对象的finalize()被调用,但是没用复活,此时对象为不可触及状态,finalize只能被调用一次

只有对象处于不可触及状态,才能被回收。

清除阶段:


标记-清除(mark-sweep)
注意,标记的不是垃圾,而是非垃圾(可达对象)。
两次遍历:
1、标记阶段,从根节点依次向下逐一遍历,找到所有的引用链。(递归遍历)
2、清除阶段 对堆内存从头至尾线性遍历,找到没用标记的对象,进行回收。

缺点:清理出来的空闲空间不连续,在新分配对象时候,内存分配采用空闲列表

复制算法:
原理和思路,就像我们理解的YGC的回收策略,Eden from to 来回倒腾。

注意点: 复制算法适合存活对象比较少的内存空间,如果对象过多,复制成本是很大的。
一般用在新生代回收

标记-压缩 mark-compact

在mark-sweep之后,进行了一次 压缩整理。
可以理解为mark-sweep-compact

其特点是 对象在发生了移动。
整理后,空闲区是规整的,新对象进行内存分配时候,可以进行指针碰撞,不再需要维护一个空闲列表

整体来说,复制算法最快,但是要移动对象,且浪费内存。
标记压缩速度最慢,且移动对象,但是空间开销很少,且没用内存碎片
标记清除速度中等,不需要移动对象,空间开销小,但是会产生一些内存碎片。

分代收集:
对不同生命周期的对象采取不同的收集方式,提高回收效率。
比如我们现在用的Hotspot虚拟机将对象分为:
年轻代
老年代


增量式收集:用户线程与GC线程并发执行,尽可能减少STW
其实仍是给予标记清除和 复制算法。允许垃圾收集线程以分阶段的方式,完成标记、清理或复制。
但是这样频繁进行线程和上下文切换,增大系统开销,降低系统吞吐量,而且并发执行,要处理好一致性问题,对垃圾与非垃圾要做进一步的修正标记。

相关文章:

【JVM】 垃圾回收篇——自问自答(1)

Q什么是垃圾&#xff1a; 运行程序中&#xff0c;没用任何指针指向的对象。 Q为什么需要垃圾回收&#xff1f; 内存只分配&#xff0c;不整理回收&#xff0c;迟早会被消耗完。 内存碎片的整理&#xff0c;为新对象腾出空间 没有GC程序无法正常进行。 Q 哪些区域有GC&#…...

Image Line FL Studio v21.0.3.3517 Producer版全插件版WIN免费下载完整版

FL Studio 21&#xff0c;也称为 Fruity Loops 21&#xff0c;是一款功能强大的数字音频工作站&#xff0c;被世界各地的音乐制作人和 DJ 使用。无论您是新手还是经验丰富的制作人&#xff0c;FL Studio 21都能为您提供创作专业品质音乐所需的工具。在这篇博文中&#xff0c;我…...

PHP8条件控制语句-PHP8知识详解

我们昨天说了流程控制的结构有顺序结构、选择结构和循环结构。选择结构就是条件结构。 条件控制语句就是对语句中不同条件的值进行判断&#xff0c;进而根据不同的条件执行不同的语句。 在本文中&#xff0c;学习的是if语句、if…else语句、if…elseif语句和switch语句。 1、…...

【PHP代码审计】ctfshow web入门 php特性 93-104

ctfshow web入门 php特性 93-104 web 93web 94web 95web 96web 97web 98web 99web 100web 101web 102web 103web 104 web 93 这段PHP代码是一个简单的源码审计例子&#xff0c;让我们逐步分析它&#xff1a; include("flag.php");: 这行代码将flag.php文件包含进来。…...

CSS元素的显示模式

1、现在我想做成小米左侧边栏这样的效果&#xff0c;该怎么做呢&#xff1f; 2、小米商城触碰之后会显示出新的商品案例 3、一碰到之后会出现这个列表 4、这里涉及到了元素显示模式&#xff1a; 5、用人进行划分可以分为男人和女人&#xff0c;根据男人和女人的特性进行相应的…...

Go strings.Title方法被废弃(Deprecated)

strings.Title的使用 在传统中&#xff0c;我们可以通过如下形式将每个单词的首字母变成大写字母&#xff0c;示例如下&#xff1a; func TestTitle(t *testing.T) { fmt.Println(strings.Title("hello world")) fmt.Println(strings.Title("hell golang&qu…...

vuejs源码分析之全局API(vm.$off)

vue在初始化的时候会给vue对象本身挂载一些全局的api。今天我们一个一个来看这些api。 vm.$off方法 这个方法是用来移除自定义事件监听器。 他的用法 vm.$off(event, calback)第一个参数event取值可以是string字符串&#xff0c;也可以是Array<string>也就是说既可以删…...

elasticSearch常见的面试题

常见的面试问题 描述使用场景 es集群架构3个节点&#xff0c;根据不同的服务创建不同的索引&#xff0c;根据日期和环境&#xff0c;平均每天递增60*2&#xff0c;大约60Gb的数据。 调优技巧 原文参考&#xff1a;干货 | BAT等一线大厂 Elasticsearch面试题解读 - 掘金 设计阶…...

第一课-前提-Stable Diffusion 教程

学习 SD 的前提是电脑配置! SD 参考配置: 建议选择台式机 i5 CPU, 内存16GB,N卡 RTX3060, 8G显存以上的配置(最低配) 在此基础上的配置越高越好。 比如,cpu i7 更好,显卡能有 RTX4090 更好,32显存要能有最好,嘿嘿嘿。 如何查看自己的显卡配置? Win+R 输入 “dxdiag…...

Python 开发工具 Pycharm —— 使用技巧Lv.2

pydoc是python自带的一个文档生成工具&#xff0c;使用pydoc可以很方便的查看类和方法结构 本文主要介绍&#xff1a;1.查看文档的方法、2.html文档说明、3.注释方法、 一、查看文档的方法 **方法1&#xff1a;**启动本地服务&#xff0c;在web上查看文档 命令【python3 -m…...

代码随想录第39天 | 62. 不同路径、63.不同路径II

62. 不同路径 动态规划五部曲&#xff1a; dp[i][j] &#xff1a;表示从&#xff08;0 &#xff0c;0&#xff09;出发&#xff0c;到(i, j) 有dp[i][j]条不同的路径。想要求dp[i][j]&#xff0c;只能有两个方向来推导出来&#xff0c;即dp[i - 1][j] 和 dp[i][j - 1]。dp[i]…...

QMT入门—初识QMT

对于普通投资者来说&#xff0c;每天实时盯盘实在是无聊又无趣&#xff0c;特别是临时有事还会错过行情。如果能把自己的投资策略用代码实现&#xff0c;通过程序来自动买卖股票那该有多好&#xff0c;这样就不会错过行情也不会不按交易纪律来操作了。 解决办法有两种&#xf…...

C 语言的 return 语句

有返回值的函数要带 return 语句, return 后面是一个表达式, return 语句将表达式的值返回给主调函数. 一个函数也可以有多个 return 语句, 比如存在于不同的分支中, 但只能有一条 return 语句被执行, 然后程序的控制权就从被调函数传到主调函数. 对于有返回值但没有带 retur…...

企业级Vue路由角色权限应该怎么做?

角色权限 角色权限&#xff0c;简单来说就是登录的用户能看到系统的哪些页面&#xff0c;不能看到系统的哪些页面。一般是后台管理系统才会涉及到如此复杂的角色权限。 对于 vue 技术栈&#xff0c;实现角色权限一般有两种方式。 第一种是利用 beforeEach 全局前置守卫。 第…...

3.2.0 版本预告!Apache DolphinScheduler API 增强相关功能

Apache DolphinScheduler 3.2.0 版本即将发布&#xff0c;在此之前&#xff0c;为了让用户提前了解到大家所期待的新功能&#xff0c;我们制作了视频来”剧透“一些核心新发布。此前&#xff0c;我们比较全面地”剧透“的 3.2.0 版本的新功能&#xff0c;这次&#xff0c;我们来…...

测试工程师的工作

目录 1.何为软件测试工程师&#xff1f; 2.软件测试工程师的职责&#xff1f; 3.为什么要做软件测试&#xff1f; 4.软件测试的前途如何&#xff1f; 5.工具和思维谁更重要&#xff1f; 6.测试和开发相差大吗&#xff1f; 7.成为测试工程师的必备条件 8.测试的分类有哪…...

压力测试与测试工具jmeter的介绍

目录 一、性能指标 二、jmeter &#xff08;一&#xff09;JMeter 安装 &#xff08;二&#xff09;JMeter 压测示例 1、添加线程组 2、添加 HTTP 请求 3、添加监听器 4、启动压测&查看分析结果 &#xff08;三&#xff09;JMeter Address Already in use 错误解决 压力测…...

解析整型最大值(Integer.MIN_VALUE)溢出变为最小值(Integer.MAX_VALUE)

解析整型最大值(Integer.MIN_VALUE)溢出变为最小值(Integer.MAX_VALUE)结论分析 解析整型最大值(Integer.MIN_VALUE)溢出变为最小值(Integer.MAX_VALUE) 解析整型最大值(Integer.MIN_VALUE)溢出变为最小值(Integer.MAX_VALUE) &#xff0c;java 二进制 最小值 减法 减1 结论 …...

【openpcdet】dbinfo内的信息

这就是kitti_dbinfos_train_sfd_seguv.pkl中【car】类别存储的信息。...

clickhouse查询缓存

为了实现最佳性能&#xff0c;数据库需要优化其内部数据存储和处理管道的每一步。但是数据库执行的最好的工作是根本没有完成的工作&#xff01;缓存是一种特别流行的技术&#xff0c;它通过存储早期计算的结果或远程数据来避免不必要的工作&#xff0c;而访问这些数据的成本往…...

vue中使用Base64加密、解密以及des加密、解密

Base64加密、解密 第一步&#xff1a; npm install js-base64 --save 下载依赖 第二步&#xff1a; 直接引入即可 import { Base64 } from js-base64; 第三步&#xff1a; Base64.encode(xxxx) 其中 .encode() 加密 .decode() 解密 中间不需要使用加密的key等…...

关于丢失安卓秘钥的撞sha-1值的办法

实验得知&#xff0c;安卓sha-1和keytool生成秘钥签名文件的时间有关。 前提条件是&#xff0c;开发者必须知道生成秘钥的所有细节参数 以下是撞文件代码&#xff08;重复生成&#xff09; import time import osidx 0while True:cmdkeytool -keyalg RSA -genkeypair -alia…...

maven如何打包你会吗?

1.新建一个maven项目&#xff0c;在main/java中建立Main类 public class Main {public static void main(String[] args) {System.out.println("hello java ...");} } 2.添加依赖&#xff0c;使其成为可执行包 <build><plugins><!--打包成为可执行包-…...

idea 控制台 打印 Tomcat日志Tomcat Catalina Log控制台乱码问题

修改tomcat的日志配置文件 conf一>logging.properties 修改【1catalina.org.apache.juli.AsyncFileHandler.encoding】的值为gbk 1catalina.org.apache.juli.AsyncFileHandler.level FINE 1catalina.org.apache.juli.AsyncFileHandler.directory ${catalina.base}/logs 1…...

python我的世界

我的世界不知道大家有没有玩过&#xff0c;今天博主用python的Ursina库复刻了我的世界给大家分享 安装Ursina pip install ursina 导入Ursina from ursina import * from ursina.prefabs.first_person_controller import FirstPersonController 创建app app Ursina() 创建Voxe…...

SpringBoot+vue 大文件分片下载

学习链接 SpringBootvue文件上传&下载&预览&大文件分片上传&文件上传进度 Blob & File & FileReader & ArrayBuffer VueSpringBoot实现文件的分片下载 video标签学习 & xgplayer视频播放器分段播放mp4&#xff08;Range请求交互过程可以参…...

scanf函数读取数据 清空缓冲区

scanf函数读取数据&清空缓冲区 scanf 从输入缓冲区读取数据数据的接收数据存入缓冲区scanf 中%d读取数据scanf中%c读取数据 清空输入缓冲区例子用getchar()吸收回车练习 scanf 从输入缓冲区读取数据 首先&#xff0c;要清楚的是&#xff0c;scanf在读取数据的时候&#xff…...

js 文件常用转换

获取上传文件的arrayBuffer&#xff1a;var u8arr await file.arrayBuffer() 通过arrayBuffer转换成Buffer&#xff1a;Buffer.from(u8arr) 1. Blob、File → Base64 function fileToDataURL(file) {let reader new FileReader();reader.readAsDataURL(file);reader.onload…...

基于Open3D的点云处理15-特征点

Intrinsic shape signatures (ISS) 参考 ISS关键点: 基本原理是避免在沿主要方向表现出类似分布的点上检测关键点&#xff0c;在这些点上无法建立可重复的规范参考框架&#xff0c;因此后续描述阶段很难变得有效。在剩余点中&#xff0c;显着性由最小特征值的大小决定,以便仅包…...

算法刷题Day 58 每日温度+下一个更大元素I

Day 58 单调栈 739. 每日温度 class Solution { public:vector<int> dailyTemperatures(vector<int>& temperatures) {vector<int> rst(temperatures.size());vector<int> decsStk; // 单调递减栈for (int i 0; i < temperatures.size(); i)…...