【实战JVM】-基础篇-04-自动垃圾回收

【实战JVM】-基础篇-04-自动垃圾回收

  • 自动垃圾回收
  • 1 多语言内存管理
    • 1.1 C/C++的内存管理
    • 1.2 Java的内存管理
    • 1.3 自动与手动对比
    • 1.4 应用场景
  • 2 方法区的回收
    • 2.1 回收条件
  • 3 堆回收
    • 3.1 判断是否被引用
      • 3.1.1 引用计数法
      • 3.1.2 可达性分析算法
        • 3.1.2.1 GC Root
        • 3.1.2.2 监视GC Root
        • 3.1.2.3 总结
    • 3.2 五种对象引用
      • 3.2.1 软引用
        • 3.2.1.1 软引用使用
        • 3.2.1.2 软引用回收
        • 3.2.1.3 软引用使用场景-缓存
      • 3.2.2 弱引用
      • 3.2.4 虚引用和终结器引用
    • 3.3 垃圾回收算法
      • 3.3.1 垃圾回收算法标准
      • 3.3.2 标记清除算法
      • 3.3.3 复制算法
      • 3.3.4 标记整理算法
      • 3.3.5 分代GC
        • 3.3.5.1 分代垃圾回收算法
    • 3.4 垃圾回收器
      • 3.4.1 Serial-Serial Old
      • 3.4.2 ParNew-CMS
      • 3.4.3 Parallel Scavenge-Parallel Old
      • 3.4.4 G1
        • 3.4.4.1 内存结构
        • 3.4.4.2 回收策略
        • 3.4.4.3 使用G1
      • 3.4.5 选择组合策略


自动垃圾回收

1 多语言内存管理

1.1 C/C++的内存管理

在这里插入图片描述

1.2 Java的内存管理

在这里插入图片描述

1.3 自动与手动对比

在这里插入图片描述

1.4 应用场景

在这里插入图片描述

2 方法区的回收

在这里插入图片描述

2.1 回收条件

在这里插入图片描述

3 堆回收

在这里插入图片描述

在这里插入图片描述

3.1 判断是否被引用

3.1.1 引用计数法

在这里插入图片描述

C++智能指针就采用引用计数法,但是存在缺点:

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

在这里插入图片描述

查看垃圾回收信息,采用-verbose:gc参数,但是java并没有采用引用计数法。使用的是可达性分析算法。

3.1.2 可达性分析算法

在这里插入图片描述

注:GC Root对象不可被回收

3.1.2.1 GC Root

在这里插入图片描述

  1. 线程Thread对象

    包括主线程,子线程等等。

  2. java.lang.Class对象

    系统类加载器加载的java.lang.*中的Class对象,其中包括sun.misc.Launcher类,再由sun.misc.Launcher类加载扩展类和应用程序类加载器。
    在这里插入图片描述

  3. 监视器对象

    在这里插入图片描述

3.1.2.2 监视GC Root
public class ReferenceCounting {
    private static A a2=null;

    public static void main(String[] args) throws IOException {
        A a1=new A();
        B b1=new B();
        a1.b=b1;
        b1.a=a1;
        a2=a1;
        System.in.read();

    }
}
class B {
    public A a;
}
class A {
    public B b;
}

启动arthas

java -Dfile.encoding=UTF-8 -jar arthas-boot.jar

进入ReferenceCounting,对内存进行快照

heapdump "D:\File\StudyJavaFile\JavaStudy\JVM\low\day03\resource\test2.hprof"

先把环境变量的jdk设为17再启动memoryanalyzer

在这里插入图片描述

打开刚刚的内存快照,canel取消引导

在这里插入图片描述

在这里插入图片描述

选择GC Root

在这里插入图片描述

可以看到成员变量实际在堆中存放的是直接引用

在这里插入图片描述

所有的局部变量和成员变量已经看过了,我们来找静态变量a2

private static A a2=null;
public static void main(String[] args) throws IOException {
    A a1=new A();
    B b1=new B();
    a1.b=b1;
    b1.a=a1;
    a2=a1;
    System.in.read();

}

静态变量通过应用程序加载器加载到堆中,A类应该还有个应用程序类的加载器的GCroot指向A,我们通过path to gcroot来找引用

在这里插入图片描述

在这里插入图片描述

我们可以看到有三个引用,亦可以看到应用程序加载器的父类都有哪些。

在这里插入图片描述

3.1.2.3 总结

在这里插入图片描述

3.2 五种对象引用

在这里插入图片描述

3.2.1 软引用

在这里插入图片描述

使用软引用必须创建两个对象:

  1. 软引用自身SoftReference对象
  2. 在软引用自身SoftReference对象中创建第二个对象A,才是程序真正使用的对象

在这里插入图片描述

3.2.1.1 软引用使用
public class SoftReferenceDemo2 {
    public static void main(String[] args) throws IOException {

        byte[] bytes = new byte[1024 * 1024 * 100];
        SoftReference<byte[]> softReference = new SoftReference<byte[]>(bytes);
        bytes = null;
        System.out.println(softReference.get());

        byte[] bytes2 = new byte[1024 * 1024 * 100];
        System.out.println(softReference.get());

//        byte[] bytes3 = new byte[1024 * 1024 * 100];
//        softReference = null;
        System.gc();

        System.in.read();
    }
}

设置最大堆内存-Xmx200m,启动,总共200M实际能用不到200M,自然第一个放进去第二个放不进去,然后软引用就被释放回收了,打印null

[B@7ba4f24f
null

设置最大堆内存-Xmx400m,都能发进去,并且指向同一个软引用空间

[B@7ba4f24f
[B@7ba4f24f

修改回200m,添加

byte[] bytes3 = new byte[1024 * 1024 * 100];

已经把软引用释放了,就不能添加了,自然报outofmemory

[B@7ba4f24f
null
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at chapter04.soft.SoftReferenceDemo2.main(SoftReferenceDemo2.java:20)
3.2.1.2 软引用回收

在这里插入图片描述

public class SoftReferenceDemo3 {

    public static void main(String[] args) throws IOException {

        ArrayList<SoftReference> softReferences = new ArrayList<>();
        ReferenceQueue<byte[]> queues = new ReferenceQueue<byte[]>();
        for (int i = 0; i < 10; i++) {
            byte[] bytes = new byte[1024 * 1024 * 100];
            SoftReference studentRef = new SoftReference<byte[]>(bytes,queues);
            softReferences.add(studentRef);
        }

        SoftReference<byte[]> ref = null;
        int count = 0;
        while ((ref = (SoftReference<byte[]>) queues.poll()) != null) {
            count++;
        }
        System.out.println(count);

    }
}

设置堆内存200M,只够存一个,后一个盒子把前一个盒子覆盖了,并且把前一个盒子放进queue中。所以最后一个存在,没有被回收,因此输出9

3.2.1.3 软引用使用场景-缓存

在这里插入图片描述

在这里插入图片描述

通过在软引用对象中添加一个属性 _key来方便后面的清理HashMap,如果内存不足,软引用自动清除,然后再根据引用队列中queue中存在的软引用对象,再通过软引用的属性 _key来清理HashMap完成闭环的清理缓存的操作。

public class StudentCache {

    private static StudentCache cache = new StudentCache();

    public static void main(String[] args) {
        for (int i = 0; ; i++) {
            StudentCache.getInstance().cacheStudent(new Student(i, String.valueOf(i)));
        }
    }

    private Map<Integer, StudentRef> StudentRefs;// 用于Cache内容的存储
    private ReferenceQueue<Student> q;// 垃圾Reference的队列

    // 继承SoftReference,使得每一个实例都具有可识别的标识。
    // 并且该标识与其在HashMap内的key相同。
    private class StudentRef extends SoftReference<Student> {
        private Integer _key = null;

        public StudentRef(Student em, ReferenceQueue<Student> q) {
            super(em, q);
            _key = em.getId();
        }
    }

    // 构建一个缓存器实例
    private StudentCache() {
        StudentRefs = new HashMap<Integer, StudentRef>();
        q = new ReferenceQueue<Student>();
    }

    // 取得缓存器实例
    public static StudentCache getInstance() {
        return cache;
    }

    // 以软引用的方式对一个Student对象的实例进行引用并保存该引用
    private void cacheStudent(Student em) {
        cleanCache();// 清除垃圾引用
        StudentRef ref = new StudentRef(em, q);
        StudentRefs.put(em.getId(), ref);
        System.out.println(StudentRefs.size());
    }

    // 依据所指定的ID号,重新获取相应Student对象的实例
    public Student getStudent(Integer id) {
        Student em = null;
// 缓存中是否有该Student实例的软引用,如果有,从软引用中取得。
        if (StudentRefs.containsKey(id)) {
            StudentRef ref = StudentRefs.get(id);
            em = ref.get();
        }
// 如果没有软引用,或者从软引用中得到的实例是null,重新构建一个实例,
// 并保存对这个新建实例的软引用
        if (em == null) {
            em = new Student(id, String.valueOf(id));
            System.out.println("Retrieve From StudentInfoCenter. ID=" + id);
            this.cacheStudent(em);
        }
        return em;
    }

    // 清除那些所软引用的Student对象已经被回收的StudentRef对象
    private void cleanCache() {
        StudentRef ref = null;
        while ((ref = (StudentRef) q.poll()) != null) {
            StudentRefs.remove(ref._key);
        }
    }

//    // 清除Cache内的全部内容
//    public void clearCache() {
//        cleanCache();
//        StudentRefs.clear();
//        //System.gc();
//        //System.runFinalization();
//    }
}

class Student {
    int id;
    String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

3.2.2 弱引用

在这里插入图片描述

public class WeakReferenceDemo2 {
    public static void main(String[] args) throws IOException {

        byte[] bytes = new byte[1024 * 1024 * 100];
        WeakReference<byte[]> weakReference = new WeakReference<byte[]>(bytes);
        bytes = null;
        System.out.println(weakReference.get());
        System.gc();
        System.out.println(weakReference.get());
    }
}

打印,不管有没有数据,全部回收

[B@7ba4f24f
null

3.2.4 虚引用和终结器引用

在这里插入图片描述

3.3 垃圾回收算法

在这里插入图片描述

释放不再存活对象的内存,使得程序能再次利用这部分空间。

3.3.1 垃圾回收算法标准

在这里插入图片描述

  • 最大吞吐量
  • 最大暂停时间
  • 堆使用效率

3.3.2 标记清除算法

在这里插入图片描述

  • 优点:实现简单,只需要在一阶段给每个对象维护一个标志位,第二阶段删除对象即可。
  • 缺点:碎片化问题(外部碎片),分配速度慢(扫描空闲链表,速度慢)

3.3.3 复制算法

在这里插入图片描述

在这里插入图片描述

3.3.4 标记整理算法

在这里插入图片描述

在这里插入图片描述

3.3.5 分代GC

在这里插入图片描述

在jdk8中,添加-XX:+UserSerialGC参数使用分代回收的垃圾回收器,运行程序

在arthas中使用memory命令查看内存,显示三个区域内存情况。

在这里插入图片描述

public class GcDemo0 {

    public static void main(String[] args) throws IOException {
        List<Object> list = new ArrayList<>();
        int count = 0;
        while (true){
            System.in.read();
            System.out.println(++count);
            //每次添加1m的数据
            list.add(new byte[1024 * 1024 * 1]);
        }
    }
}

添加参数 -XX:+UseSerialGC -Xms60m -Xmn20m -Xmx60m -XX:SurvivorRatio=3 -XX:+PrintGCDetails

应当是总共60M,老年代40M,新生代20M,新生代中,伊甸园12M,S0,S1各4M,满足SurvivorRatio=3的3:1:1

在这里插入图片描述

3.3.5.1 分代垃圾回收算法

在这里插入图片描述

在复制算法中,S0和S1会发生互换,第一次MinorGC全放到To中,然后To和From交换名字。

在这里插入图片描述

在这里插入图片描述

FullGC对新生代和老年代一起回收

3.4 垃圾回收器

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.4.1 Serial-Serial Old

新生代采用复制算法,老年代采用标记整理算法

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.4.2 ParNew-CMS

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.4.3 Parallel Scavenge-Parallel Old

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.4.4 G1

在这里插入图片描述

3.4.4.1 内存结构

在这里插入图片描述

在这里插入图片描述

3.4.4.2 回收策略

在这里插入图片描述

在这里插入图片描述

年轻代选择的复制算法

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.4.4.3 使用G1

在这里插入图片描述

3.4.5 选择组合策略

在这里插入图片描述

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

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

相关文章

如何用分立器件设计一个过流保护电路

过流保护电路是指当后级负载电流过大或者发生短路时&#xff0c;自动切断电源与后级负载&#xff0c;从而防止大电流损害电源电路&#xff0c;过流保护又叫OCP。 常见的过流保护电路有保险丝过流保护&#xff0c;集成的过流保护芯片&#xff0c;还有这种分立器件搭建的过流保护…

检索模型预训练方法:RetroMAE

论文title&#xff1a;https://arxiv.org/pdf/2205.12035RetroMAE: Pre-Training Retrieval-oriented Language Models Via Masked Auto-Encoder 论文链接&#xff1a;https://arxiv.org/pdf/2205.12035 摘要 1.一种新的MAE工作流&#xff0c;编码器和解器输入进行了不同的掩…

React@16.x(12)ref 转发-forwardRef

目录 1&#xff0c;介绍2&#xff0c;类组件如何使用4&#xff0c;应用场景-高阶组件HOC 1&#xff0c;介绍 上篇文章中提到&#xff0c;ref 只能对类组件使用&#xff0c;不能对函数组件使用。 而 ref 转发可以对函数组件实现类似的功能。 使用举例&#xff1a; import Re…

SCI一区 | Matlab实现PSO-TCN-LSTM-Attention粒子群算法优化时间卷积长短期记忆神经网络融合注意力机制多变量时间序列预测

SCI一区 | Matlab实现PSO-TCN-LSTM-Attention粒子群算法优化时间卷积长短期记忆神经网络融合注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现PSO-TCN-LSTM-Attention粒子群算法优化时间卷积长短期记忆神经网络融合注意力机制多变量时间序列预测预测效果基本介绍程序设…

【CCF-CSP】202309-1 202309-2 坐标变换

坐标变换&#xff08;其一&#xff09; 代码&#xff1a; #include <bits/stdc.h> using namespace std; int main(){int n,m,x,y,sumx0,sumy0;cin>>n>>m;for(int i1;i<n;i){cin>>x>>y;sumxx,sumyy;}for(int i1;i<m;i){cin>>x>&…

用天工AI写文章,节约了8个人的成本

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 当下AI工具最大的问题是什么? 是写的文章没有灵魂、没有感情、像机器人! 生成的文章官话连篇&#xff0c;人们一眼就看出是AI写的&#xff0c;这种文章怎么能给客户交差呢?自己这关都过不去&#xff0c;是吧? …

md5强弱碰撞

一&#xff0c;类型。 1.弱比较 php中的""和""在进行比较时&#xff0c;数字和字符串比较或者涉及到数字内容的字符串&#xff0c;则字符串会被转换为数值并且比较按照数值来进行。按照此理&#xff0c;我们可以上传md5编码后是0e的字符串&#xff0c;在…

四川汇聚荣聚荣科技有限公司好不好?

在当今科技飞速发展的时代&#xff0c;企业要想在激烈的市场竞争中脱颖而出&#xff0c;必须具备强大的技术实力和良好的市场口碑。那么&#xff0c;作为一家专注于科技创新的公司&#xff0c;四川汇聚荣聚荣科技有限公司究竟如何呢?接下来&#xff0c;我们将从四个方面进行详…

K210 数字识别 教程

一、烧写固件 连接k210开发板&#xff0c;点开烧录固件工具&#xff0c;选中固件&#xff0c;并下载 二、模型训练 网站&#xff1a;MaixHub 1、上传文件 2、开始标记数据 添加9个标签&#xff0c;命名为1~9&#xff0c;按键盘w开始标记&#xff0c;键盘D可以下一张图片&…

YashanDB携手慧点科技完成产品兼容认证 助力国产信创生态建设

近日&#xff0c;深圳计算科学研究院崖山数据库系统YashanDB与慧点科技顺利完成兼容性互认证。经严格测试&#xff0c;双方产品完全兼容&#xff0c;稳定运行&#xff0c;共同支撑政府、企业、金融等办公应用场景下的数字化转型升级&#xff0c;为企业的信息技术应用创新提供坚…

C++容器之位集(std::bitset)

目录 1 概述2 使用实例3 接口使用3.1 constructor3.2 count_and_size3.3 test3.4 any3.5 none3.6 all3.7 set3.8 reset3.9 filp3.10 to_string3.11 to_ulong3.12 to_ullong3.13 operators1 概述 位集存储位(只有两个可能值的元素:0或1,true或false,…)。   该类模拟bool…

【C++】<知识点> 标准模板库STL(下)

文章目录 六、set与multiset 1. 常用成员函数 2. pair模板 3. set 4. multiset 七、map与multimap 1. map 2. multimap 3. 应用实例 八、容器适配器 1. stack 2. queue 3. priority_queue 九、算法 六、set与multiset 1. 常用成员函数 iterator find(const T&am…

Kubernetes和Docker对不同OS和CPU架构的适配关系

Docker Docker官网对操作系统和CPU架构的适配关系图 对于其他发行版本&#xff0c;Docker官方表示没有测试或验证在相应衍生发行版本上的安装&#xff0c;并建议针对例如Debian、Ubuntu等衍生发行版本上使用官方的对应版本。 Kubernetes X86-64 ARM64 Debian系 √ √ Re…

鸿蒙学习第一课--认识目录结构

项目结构介绍 module.json5 src > main > module.json5&#xff1a;Stage模型模块配置文件。主要包含HAP包的配置信息、应用/服务在具体设备上的配置信息以及应用/服务的全局配置信息。具体的配置文件说明&#xff0c;详见module.json5配置文件。 资源分类和访问 关于s…

【C++题解】1133. 字符串的反码

问题&#xff1a;1133. 字符串的反码 类型&#xff1a;字符串 题目描述&#xff1a; 一个二进制数&#xff0c;将其每一位取反&#xff0c;称之为这个数的反码。下面我们定义一个字符的反码。 如果这是一个小写字符&#xff0c;则它和字符 a 的距离与它的反码和字符 z 的距离…

《当微服务遇上Ribbon:一场负载均衡的华丽舞会》

在微服务的厨房里&#xff0c;如何确保每一道服务都恰到好处&#xff1f;揭秘Spring Cloud Ribbon如何像大厨一样精心调配资源&#xff0c;让负载均衡变得像烹饪艺术一样简单&#xff01; 文章目录 Spring Cloud Ribbon 详解1. 引言微服务架构中的负载均衡需求Spring Cloud Rib…

SwiftUI中AppStorage的介绍使用

在Swift中&#xff0c;AppStorage是SwiftUI中引入的一个属性包装器&#xff0c;在这之前我们要存储一些轻量级的数据采用UserDefaults进行存取。而AppStorage用于从UserDefaults中读取值&#xff0c;当值改变时&#xff0c;它会自动重新调用视图的body属性。也就是说&#xff0…

地图数据导入

OpenStreetMap 地图数据官网 Geofabrik Download Server 下载数据 china-latest-free.shp.zip 解压到 D:\works\mapworks\shp\tmp 解压找到相关数据&#xff08;目前我要的是铁路数据&#xff09; 导入 gis_osm_railways_free_1.shp 到 pgAdmin4 数据库 1.启动 C:\Progra…

unity制作app(9)--拍照 相册 上传照片

1.传输照片&#xff08;任何较大的数据&#xff09;都需要扩展服务器的内存空间。 2.还需要base64编码 2.1客户端发送位置的编码 2.2服务器接收部分的代码

“2024 亚马逊云科技中国峰会,挑战俱乐部 Hands On 动手实验课程正在直播中,点击链接畅享生成式AI建构之旅,赢心动好礼

只看不过瘾&#xff1f;别急&#xff01;我们为您准备了【生成式AI助手 Amazon Q 初体验】动手实验&#xff0c;一款生成式人工智能 (AI) 支持的对话助理&#xff0c;可以帮助您理解、构建、扩展和操作 Amazon 应用程序&#xff0c;您可以询问有关 Amazon 架构、最佳实践、文档…