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

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

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

相关文章

爬虫013_函数的定义_调用_参数_返回值_局部变量_全局变量---python工作笔记032

然后再来看函数,可以避免重复代码 可以看到定义函数以及调用函数

Linux命令200例:mount将文件系统挂载到指定目录下(常用)

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &…

出现raise NotImplementedError报错

在学习《动手学深度学习》时&#xff0c;实现下面代码时&#xff0c;报出raise NotImplementedError错误。 import collections import torch from d2l import torch as d2l import math from torch import nnclass Seq2SeqEncoder(d2l.Encoder):def __init__(self,vocab_size,…

[虚幻引擎] UE DTBase64 插件说明 使用蓝图对字符串或文件进行Base64加密解密

本插件可以在虚幻引擎中使用蓝图对字符串&#xff0c;字节数组&#xff0c;文件进行Base64的加密和解密。 目录 1. 节点说明 String To Base64 Base64 To String Binary To Base64 Base64 To Binary File To Base64 Base64 To File 2. 案例演示 3. 插件下载 1. 节点说…

【vim 学习系列文章 4 - vim与系统剪切板之间的交互】

文章目录 背景1.1.1 vim支持clipboard 检查1.1.2 vim的寄存器 上篇文章&#xff1a;【vim 学习系列文章 3 - vim 选中、删除、复制、修改引号或括号内的内容】 背景 从vim中拷贝些文字去其它地方粘贴&#xff0c;都需要用鼠标选中vim的文字后&#xff0c;Ctrlc、Ctrlv&#x…

自定义注解(Annontation)

目录 1.注解定义 2.元注解定义 3. 自定义注解&#xff08;自定义的注解名称相同的会覆盖原注解&#xff09; 4.Annotation架构&#xff08;元注解参数介绍&#xff09; 1.注解定义 注解是用来将任何的信息或元数据&#xff08;metadata&#xff09;与程序元素&#xff08;类…

Leetcode.1289 下降路径最小和 II

题目链接 Leetcode.1289 下降路径最小和 II rating : 1697 题目描述 给你一个 n x n 整数矩阵 g r i d grid grid &#xff0c;请你返回 非零偏移下降路径 数字和的最小值。 非零偏移下降路径 定义为&#xff1a;从 g r i d grid grid 数组中的每一行选择一个数字&#xff…

ORACLE行转列、列转行实现方式及案例

ORACLE行转列、列转行实现方式及案例 行转列案例方式1.PIVOT方式2.MAX和DECODE方式3.CASE WHEN和GROUP BY 列转行案例方式1.UNPIVOT方式2.UNION ALL 行转列 案例 假设我们有一个名为sales的表&#xff0c;其中包含了产品销售数据。表中有三列&#xff1a;product&#xff08;…

windows为nginx添加定时任务(开机延迟启动)

windows开机启动任务 调用定时任务管理器选中windows创建基本任务设置名称和描述设置触发器 并且添加个延迟触发设置操作设置条件配置设置 调用定时任务管理器 winr 输入 taskschd.msc回车 选中windows创建基本任务 设置名称和描述 设置触发器 并且添加个延迟触发 设置操作 …

【uniapp】 软键盘弹出后fixed定位被顶上去问题

问题描述 当手机设计的导航栏为fixed定位上去时&#xff0c;输入框获取焦点就会把顶部自定义的导航栏顶到上面去&#xff0c;如下图所示 解决办法 输入框设置 :adjust-position“false” <input type"text" :adjust-position"false" focus"i…

算法基础简介

目录 1、递归 2、二分查找 3、排序算法 分类 3.1、冒泡排序 3.2、选择排序 3.3、插入排序 3.4、希尔排序(高级插入排序) 3.5、归并排序 3.6、快速排序 核心思想 具体步骤 代码实现 3.7、堆排序 3.8、计数排序 3.9、桶排序 3.10、基数排序 4、字符串匹…

【80天学习完《深入理解计算机系统》】第三天 2.3 整数运算【正负溢出】【运算的溢出】【类型转换的二进制扩展】

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…

数据库的约束 详解

一、约束的概述 1.概念:约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 2&#xff0e;目的:保证数据库中数据的正确、有效性和完整性。 3.分类: 约束描述关键字非空约束限制该字段的数据不能为nullNOT NULL唯一约束保证该字段的所有数据都是唯一、不…

全球飞机电磁阀总体规模分析

电磁阀是一种液压管路的电磁装置&#xff0c;通过使用电流产生磁场&#xff0c;从而驱动螺线管&#xff0c;控制阀中流体的流动。电磁阀作为流体控制自动化系统的执行器之一&#xff0c;有着结构紧凑、尺寸小、重量轻、密封良好、维修简便和可靠性高、节能降耗的特点&#xff0…

如何安全变更亚马逊收款账户?

有太多的卖家想知道如何安全变更亚马逊收款账户&#xff0c;因为更改了第三方收款账户可能会导致二次视频认证或者增强视频。真的是这样吗&#xff1f; 其实不推荐亚马逊店铺正常运营之后去变更信用卡&#xff0c;收款账户等重要资料的&#xff0c;因为玩黑科技的卖家也真的多…

[C++ 网络协议] 套接字

目录 1. 套接字 1.1 在Linux平台下构建套接字 1.1.1 用于接听的套接字(服务器端套接字) 1.1.2 用于发送请求的套接字(客户端套接字) 1.2 在Windows平台下构建套接字 1.2.1 Winsock的初始化 1.2.2 用于接听的套接字(服务器端套接字) 1.2.3 用于发送请求的套接字(客户端套…

vue+neo4j(neo4j desktop安装和使用)

vueneo4j&#xff08;neo4j desktop安装和使用&#xff09; 本文目录 vueneo4j&#xff08;neo4j desktop安装和使用&#xff09;官网下载安装基本使用创建项目新增数据库连接数据库 使用cypher构建简单知识图谱创建节点创建关系删除节点及关系查询节点和关系 数据导出为json文…

Stable Diffusion - 俯视 (from below) 拍摄的人物图像 LoRA 与配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132192139 图像来自 哥特风格 LoRA 俯视 LoRA&#xff0c;提升视觉冲击力&#xff0c;核心配置 <lora:view_from_below:0.6>,(from below,…

JVM工作的总体机制概述

JDK、JRE、JVM关系回顾 JVM&#xff1a;Java Virtual Machine&#xff0c;翻译过来是Java虚拟机JRE&#xff1a;Java Runtime Environment&#xff0c;翻译过来是Java运行时环境 JREJVMJava程序运行时所需要的类库JDK&#xff1a;Java Development Kits&#xff0c;翻译过来是…

LeetCode--HOT100题(25)

目录 题目描述&#xff1a;141. 环形链表&#xff08;简单&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;141. 环形链表&#xff08;简单&#xff09; 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连…