【JVM基础篇】Java垃圾回收器介绍

news2024/11/29 12:56:28

垃圾回收器(垃圾回收算法实现)

垃圾回收器是垃圾回收算法的具体实现。由于垃圾回收器分为年轻代和老年代,除了G1(既能管控新生代,也可以管控老年代)之外,新生代、老年代的垃圾回收器必须按照hotspot的要求成对组合进行使用(需要根据JDK的版本来选择相应的组合)

具体的组合关系如下:

在这里插入图片描述

JVM底层源码中,在某些特殊情况,CMS回收器会调用Serial Old回收器

Arthas查看所使用的垃圾回收器

不能直接看到使用了什么垃圾回收器,只能根据算法来推断

在这里插入图片描述

年轻代-Serial垃圾回收器

Serial是一种单线程串行回收年轻代的垃圾回收器。

在这里插入图片描述

回收年代和算法

  • 年轻代
  • 复制算法

优点

单CPU处理器下吞吐量非常出色

缺点

多CPU下吞吐量不如其他垃圾回收器(单线程,只使用了一个CPU),堆如果偏大会让用户线程处于长时间的等待

适用场景

Java编写的客户端程序或者硬件配置有限(CPU核数不多)的场景

如何使用

-XX:+UseSerialGC:新生代、老年代都使用串行回收器。

老年代-SerialOld垃圾回收器

SerialOld是Serial垃圾回收器的老年代版本,采用单线程串行回收

在这里插入图片描述

回收年代和算法

  • 老年代
  • 标记-整理算法

优点

单CPU处理器下吞吐量非常出色

缺点

多CPU下吞吐量不如其他垃圾回收器,堆如果偏大会让用户线程处于长时间的等待

适用场景

与Serial垃圾回收器搭配使用,或者在CMS特殊情况下使用

如何使用

-XX:+UseSerialGC:新生代、老年代都使用串行回收器。

年轻代-ParNew垃圾回收器

ParNew垃圾回收器本质上是对Serial在多CPU下的优化,使用多线程进行垃圾回收

在这里插入图片描述

回收年代和算法:

  • 年轻代
  • 复制算法

优点

  • 多CPU处理器下停顿时间较短

缺点

  • 吞吐量和停顿时间不如G1,所以在JDK9之后不建议使用

适用场景

  • JDK8及之前的版本中,与CMS老年代垃圾回收器搭配使用

如何使用

  • -XX:+UseParNewGC:新生代使用ParNew回收器, 老年代使用串行回收器

在这里插入图片描述

老年代-CMS(Concurrent Mark Sweep)垃圾回收器

CMS垃圾回收器关注的是系统的暂停时间(尽量减少STW,优化用户体验),允许用户线程和垃圾回收线程在某些步骤中同时执行,减少了用户线程的等待时间。

回收年代和算法

  • 老年代
  • 标记清除算法

优点

  • 系统由于垃圾回收出现的停顿时间较短,用户体验好

缺点

1、内存碎片问题

2、退化问题(在某些特定情况,会退化为SerialOld这种单线程回收器)

3、浮动垃圾问题(回收过程,有的垃圾回收不掉)

适用场景

大型的互联网系统中用户请求数据量大、频率高的场景,比如订单接口、商品接口等

使用

XX:+UseConcMarkSweepGC,可以分别设置年轻代和老年代的回收器

在这里插入图片描述

在这里插入图片描述

CMS执行步骤

  1. 初始标记,用极短的时间标记出GC Roots能直接关联到的对象
  2. 并发标记, 标记所有的对象,用户线程不需要暂停。(虽然并发标记是和用户线程一起执行,但是如果并发标记占用的资源较高,也会影响用户线程)
  3. 重新标记(并发),由于并发标记阶段有些对象会发生了变化,存在错标(用的对象本来是存活的,标记之后,用户线程把它变得不存活了,导致错标)、漏标(因为是并发的,可能有的对象是用户线程刚刚创建出来的,就会导致漏标)等情况,需要重新标记。
  4. 并发清理,清理死亡的对象,用户线程不需要暂停。

注:只有初始标记、重新标记阶段会出现STW

在这里插入图片描述

缺点:

1、CMS使用了标记-清除算法,在垃圾收集结束之后会出现大量的内存碎片,为了不影响对象的分配,CMS会在Full GC时进行碎片的整理。这样会导致用户线程暂停,可以使用-XX:CMSFullGCsBeforeCompaction=N 参数(默认0)调整N次Full GC之后再整理

2.、无法处理在并发清理过程中产生的“浮动垃圾”,不能做到完全的垃圾回收(在本次清理的过程中,用户线程并发创建了一些对象,但是很快没有再使用,这些对象在这次清理中没有得到回收,需要等到下一次清理,所以称这些为浮动垃圾)。

3、如果老年代内存不足无法分配对象,CMS就会退化成Serial Old单线程回收老年代。

并发线程数:

在CMS中并发阶段运行时的线程数可以通过-XX:ConcGCThreads参数设置,由系统计算得出,计算公式为(-XX:ParallelGCThreads定义的线程数 + 3) / 4, ParallelGCThreads是STW停顿之后的并行线程数

ParallelGCThreads是由处理器核数决定的:

1、当cpu核数小于8时,ParallelGCThreads = CPU核数

2、否则 ParallelGCThreads = 8 + (CPU核数 – 8 )*5/8

我的电脑上逻辑处理器有12个,所以ParallelGCThreads = 8 + (12 - 8)* 5/8 = 10,ConcGCThreads = (-XX:ParallelGCThreads定义的线程数 + 3) / 4 = (10 + 3) / 4 = 3

在这里插入图片描述

最终可以得到这张图:

在这里插入图片描述

并发标记和并发清理阶段,会使用3个线程并行处理。重新标记阶段会使用10个线程处理。由于CPU的核心数有限,并发阶段会影响用户线程执行的性能。

在这里插入图片描述

年轻代-Parallel Scavenge垃圾回收器

Parallel Scavenge是JDK8默认的年轻代垃圾回收器,多线程并行回收关注的是系统的吞吐量。为了拉高吞吐量,PS会自动调整堆内存大小(调整新生代、老年代内存大小、晋升的阈值)

在这里插入图片描述

回收年代和算法

  • 年轻代
  • 复制算法

优点

  • 吞吐量高,而且支持手动设置参数控制吞吐量。为了提高吞吐量,虚拟机会动态调整堆的参数(用户只需要设置吞吐量,不需要设置内存大小等其他参数)

缺点

  • 不能保证单次的停顿时间,但是支持设置STW时间

适用场景

  • 后台任务,不需要与用户交互,并且容易产生大量的对象。比如:大数据的处理,大文件导出

常用参数

Parallel Scavenge允许手动设置最大暂停时间和吞吐量。Oracle官方建议在使用这个组合时,不要设置堆内存的最大值,垃圾回收器会根据最大暂停时间和吞吐量自动调整内存大小。

  • 最大暂停时间,-XX:MaxGCPauseMillis=n 设置每次垃圾回收时的最大停顿毫秒数
  • 吞吐量,-XX:GCTimeRatio=n 设置吞吐量为n(用户线程执行时间 = n/(n + 1))
  • 自动调整内存大小, -XX:+UseAdaptiveSizePolicy设置可以让垃圾回收器根据吞吐量和最大停顿的毫秒数自动调整内存大小,这个参数默认是开启的(Oracle建议使用PS组合的时候,不要设置堆内存的最大值,让垃圾回收器自动调整)

注:最大暂停时间和吞吐量这两个指标是冲突的,垃圾回收器会尽量满足最大暂停时间(有时候设置得太小,是没办法满足的,会超出所设置得最大暂停时间),牺牲吞吐量。如果要同时设置最大暂停时间和吞吐量,要多做测试,让它们比较协调

老年代-Parallel Old垃圾回收器

Parallel Old是为Parallel Scavenge收集器设计的老年代版本,利用多线程并发收集。

在这里插入图片描述

回收年代和算法

  • 老年代
  • 标记-整理算法(其实是标记+清除+整理)

优点

  • 并发收集,在多核CPU下效率较高

缺点

  • 暂停时间会比较长

适用场景

  • 与Parallel Scavenge配套使用

如何使用

JDK8设置参数,就是默认使用该回收器

参数:-XX:+UseParallelGC-XX:+UseParallelOldGC可以使用Parallel Scavenge + Parallel Old这种组合。
在这里插入图片描述

在这里插入图片描述

测试

-XX:+PrintFlagsFinal:可以在程序启动的时候打印所有配置项的最终值,可以看看自动调整功能有没有开启

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 垃圾回收器案例3
 */
//-XX:+UseSerialGC -Xmn1g -Xmx16g -XX:SurvivorRatio=8  -XX:+PrintGCDetails -verbose:gc -XX:+PrintFlagsFinal
//-XX:+UseParNewGC  -Xmn1g -Xmx16g -XX:SurvivorRatio=8  -XX:+PrintGCDetails -verbose:gc
//-XX:+UseConcMarkSweepGC
//-XX:+UseG1GC   -Xmn8g -Xmx16g -XX:SurvivorRatio=8  -XX:+PrintGCDetails -verbose:gc MaxGCPauseMillis
//-XX:+PrintFlagsFinal  -XX:GCTimeRatio = 19  -XX:MaxGCPauseMillis=10 -XX:+UseAdaptiveSizePolicy
public class GcDemo2 {

    public static void main(String[] args) throws IOException {
        int count = 0;
        List<Object> list = new ArrayList<>();
        while (true){
            //System.out.println(++count);
            if(count++ % 10240 == 0){
                list.clear();
            }
//            byte[] bytes = new byte[1024 * 1024 * 1];
            list.add(new byte[1024 * 1024 * 1 / 2]);
//            System.gc();
        }
    }
}

【测试最大暂停时间=10】

在这里插入图片描述

内存大小如下:

在这里插入图片描述

【测试最大暂停时间=1】

在这里插入图片描述

在这里插入图片描述

结论:堆内存越小,垃圾回收暂停时间越短

G1(Garbage First)垃圾回收器(极力推荐)

JDK9之后默认的垃圾回收器是G1(Garbage First)垃圾回收器。

  • Parallel Scavenge关注吞吐量,允许用户设置最大暂停时间 ,但是会减少年轻代可用空间的大小。
  • CMS关注暂停时间,但是吞吐量方面会下降。
  • 而G1设计目标就是将上述两种垃圾回收器的优点融合:

JDK9之后强烈建议使用G1垃圾回收器。(在JDK7、8上,G1可能不是很成熟,要慎重考虑)

G1出现之前的垃圾回收器,年轻代和老年代一般是连续的,如下图:

在这里插入图片描述

G1内存结构发生了变化:G1的整个堆会被划分成多个大小相等的区域,称之为区Region,区域不要求是连续的。分为Eden、Survivor、Old区。Region的大小通过堆空间大小/2048计算得到,也可以通过参数-XX:G1HeapRegionSize=32m指定(其中32m指定region大小为32M),Region size必须是2的指数幂,取值范围从1M到32M。

在这里插入图片描述

G1垃圾回收有两种方式

1、年轻代回收(Young GC)

2、混合回收(Mixed GC)

年轻代回收(Young GC)

只回收年轻代,回收Eden区和Survivor区中不用的对象。会导致STW,G1中可以通过参数

-XX:MaxGCPauseMillis=n(默认200) 设置每次垃圾回收时的最大暂停时间毫秒数,G1垃圾回收器会尽可能地保证暂停时间。

【Young GC步骤】

1、新创建的对象会存放在Eden区。当G1判断年轻代区不足(max默认60%,如果年轻代的内存占了总堆的60%以上,就要Young GC),无法分配对象时需要回收时会执行Young GC。

在这里插入图片描述

2、标记出Eden和Survivor区域中的存活对象,

3、根据配置的**最大暂停时间选择某些区域(和其他回收器的区别:其他回收器会回收负责的所有区域)**将存活对象复制到一个新的Survivor区中(年龄+1)(使用复制算法,不会产生内存碎片),清空这些区域。

在这里插入图片描述

在这里插入图片描述

G1在进行Young GC的过程中会去记录每次垃圾回收时每个Eden区和Survivor区的平均耗时,以作为下次回收时的参考依据。这样就可以根据配置的最大暂停时间计算出本次回收时最多能回收多少个Region区域了。比如-XX:MaxGCPauseMillis=n(默认200),每个Region回收耗时40ms,那么这次回收最多只能回收4个Region。

4、后续Young GC时与之前相同,只不过Survivor区中存活对象会被搬运到另一个Survivor区。

在这里插入图片描述

在这里插入图片描述

5、当某个存活对象的年龄到达阈值(默认15),将被放入老年代。原来的Survivor中年龄没有到达15的对象,还是会迁移到新的Survivor中。

在这里插入图片描述

6、部分对象如果大小超过Region的一半,会直接放入老年代,这类老年代被称为Humongous(翻译:巨大的)区。比如堆内存是4G,每个Region是2M,只要一个大对象超过了1M就被放入Humongous区,如果对象过大会横跨多个Region(一个Region放不完)

在这里插入图片描述

7、多次回收之后,会出现很多Old老年代区,此时总堆占有率达到阈值时

-XX:InitiatingHeapOccupancyPercent默认45%)会触发混合回收Mixed GC,回收所有年轻代和部分老年代的对象以及大对象区。采用复制算法来完成。

在这里插入图片描述

在这里插入图片描述

混合回收(Mixed GC)

混合回收分为如下步骤,看起来和CMS差不多,但是步骤里面都是有区别的:

  • 初始标记(initial mark)
  • 并发标记(concurrent mark)
  • 最终标记(remark或者Finalize Marking):只管漏标,不管新创建、不再关联的对象。这里使用的算法远比CMS的快
  • 并发清理(cleanup):G1对老年代的清理会选择存活度最低的区域来进行回收(A区:100个对象只存活1个;B区:100个对象存活99个;G1选择回收A区),这样可以保证回收效率最高,这也是G1(Garbage first)名称的由来。最后清理阶段使用复制算法,不会产生内存碎片。

在这里插入图片描述

在这里插入图片描述

注意:**如果清理过程中发现没有足够的空Region存放转移的对象,会出现Full GC,**单线程执行标记-整理算法,此时会导致用户线程的暂停,影响用户的正常使用。所以尽量保证应该用的堆内存有一定多余的空间,如果堆内存的占用比较高,就要考虑优化。

在这里插入图片描述

如何使用G1垃圾回收器

参数1: -XX:+UseG1GC 打开G1的开关,JDK9之后默认不需要打开

参数2:-XX:MaxGCPauseMillis=毫秒值 最大暂停的时

回收年代和算法

  • 年轻代+老年代
  • 复制算法

优点

  • 支持巨大的堆空间回收,并有较高的吞吐量。对比较大的堆延迟可控,如超过6G的堆回收时
  • 不会产生内存碎片
  • 并发标记的SATB算法效率高,比CMS的算法效率高
  • 支持多CPU并行垃圾回收
  • 允许用户设置最大暂停时间

缺点

  • JDK8的早期版本还不够成熟

适用场景

  • JDK8最新版本、JDK9之后建议默认使用

测试

使用以下代码测试g1垃圾回收器,打印出每个阶段的时间:

在这里插入图片描述

package chapter04.gc;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 垃圾回收器案例3
 */
//-XX:+UseG1GC   -Xmn8g -Xmx16g -XX:SurvivorRatio=8  -XX:+PrintGCDetails -verbose:gc 
public class GcDemo2 {

    public static void main(String[] args) throws IOException {
        int count = 0;
        List<Object> list = new ArrayList<>();
        while (true){
            //System.out.println(++count);
            if(count++ % 10240 == 0){
                list.clear();
            }
//            byte[] bytes = new byte[1024 * 1024 * 1];
            list.add(new byte[1024 * 1024 * 1 / 2]);
//            System.gc();
        }
    }
}

每个region大小为2m,一共有84个young区,26个幸存者区。

在这里插入图片描述

初始标记花了0.0478秒,初始标记是伴随着年轻代回收的,0.0478秒是两个操作的总时间
在这里插入图片描述

在这里插入图片描述

并发标记总共耗时10ms,不会产生STW。

在这里插入图片描述

最终标记,效率较高

在这里插入图片描述

清理阶段

在这里插入图片描述

垃圾回收器总结

垃圾回收器的组合关系虽然很多,但是针对几个特定的版本,比较好的组合选择如下:

  • JDK8及之前:
    • ParNew + CMS(关注暂停时间)
    • Parallel Scavenge + Parallel Old (关注吞吐量)
    • G1(JDK8之前不建议,较大堆并且关注暂停时间)
  • JDK9之后:G1(默认)。从JDK9之后,由于G1日趋成熟,JDK默认的垃圾回收器已经修改为G1,所以强烈建议在生产环境上使用G1。G1的实现原理将在《原理篇》中介绍,更多前沿技术ZGC(最新的垃圾回收器)、GraalVM将在《高级篇》中介绍。

几个问题

Java中有哪几块内存需要垃圾回收?

在这里插入图片描述

方法区回收,Java程序员少关注

在这里插入图片描述

在这里插入图片描述

有哪几种常见的引用类型?

  • 强引用,最常见的引用方式,由可达性分析算法来判断
  • 软引用,对象在没有强引用情况下,内存不定时会回收
  • 弱引用,对象在没有强引用情况下,会直接回收
  • 虚引用,通过虚引用知道对象被回收了
  • 终结器引用,对象回收时可以自救,不建议使用

有哪几种常见的垃圾回收算法?

在这里插入图片描述

常见的垃圾回收器有哪些?

  • Serial+Serial Old:单线程回收,适用于单核CPU场景
  • ParNew+CMS:暂停时间较短,适用于大型互联网应用中与用户交互的部分
  • Paraller Scavenge+Parallel Old:吞吐量高,适用于后台进行大量数据操作
  • G1:适用于较大堆,具有可控暂停时间

文章说明

该文章是本人学习 黑马程序员 的学习笔记,文章中大部分内容来源于 黑马程序员 的视频黑马程序员JVM虚拟机入门到实战全套视频教程,java大厂面试必会的jvm一套搞定(丰富的实战案例及最热面试题),也有部分内容来自于自己的思考,发布文章是想帮助其他学习的人更方便地整理自己的笔记或者直接通过文章学习相关知识,如有侵权请联系删除,最后对 黑马程序员 的优质课程表示感谢。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python】组合数据类型:序列,列表,元组,字典,集合

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️Python】 文章目录 前言组合数据类型序列类型序列常见的操作符列表列表操作len()append()insert()remove()index()sort()reverse()count() 元组三种序列类型的区别 集合类型四种操作符集合setfrozens…

tongweb 部署软航流版签一体化应用示例 提示跨域错误CORS ERROR

目录 问题现象与描述 解决办法 原理解析 什么是CORS 浏览器跨域请求限制 跨域问题解决方法 跨域请求流程 浏览器请求分类解析 http请求方法简介 问题现象与描述 重庆软航科技有限公司提供了一套针对针对word、excel等流式文件转换成PDF版式文件并进行版式文件在线签章…

什么是 DDoS 攻击及如何防护DDOS攻击

自进入互联网时代&#xff0c;网络安全问题就一直困扰着用户&#xff0c;尤其是DDOS攻击&#xff0c;一直威胁着用户的业务安全。而高防IP被广泛用于增强网络防护能力。今天我们就来了解下关于DDOS攻击&#xff0c;以及可以防护DDOS攻击的高防IP该如何正确选择使用。 一、什么是…

Apache Seata分布式事务启用Nacos做配置中心

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Seata分布式事务启用Nacos做配置中心 Seata分布式事务启用Nacos做配置中心 项目地址 本文作…

matlab 有倾斜的椭圆函数图像绘制

matlab 有倾斜的椭圆函数图像绘制 有倾斜的椭圆函数图像绘制xy交叉项引入斜线负向斜线成分正向斜线成分 x^2 y^2 xy 1 &#xff08;负向&#xff09;绘制结果 x^2 y^2 - xy 1 &#xff08;正向&#xff09;绘制结果 有倾斜的椭圆函数图像绘制 为了确定椭圆的长轴和短轴的…

复现YOLO_ORB_SLAM3_with_pointcloud_map项目记录

文章目录 1.环境问题2.遇到的问题2.1编译问题1 monotonic_clock2.2 associate.py2.3 associate.py问题 3.运行问题 1.环境问题 首先环境大家就按照github上的指定环境安装即可 环境怎么安装网上大把的资源&#xff0c;自己去找。 2.遇到的问题 2.1编译问题1 monotonic_cloc…

STMF4学习笔记RTC(天空星)

前言&#xff1a;本篇笔记参考嘉立创文档&#xff0c;连接放在最后 #RTC相关概念定义 Real-Time Clock 缩写 RTC 翻译 实时时钟&#xff0c;是单片机片内外设的一种&#xff0c;作用于提供准确的时间还有日期&#xff0c;这个外设有独立的电源&#xff0c;当单片机停止供电…

C++之static关键字

文章目录 前提正文多重定义extern关键字使用staticstatic 全局变量(在.cpp文件中定义)static变量存放在哪里static变量可不可以放在.h文件中 static 函数static局部变量static 成员变量static 成员函数 总结参考链接 前提 好吧&#xff0c;八股&#xff0c;我又回来了。这次想…

【wordpress教程】wordpress博客网站添加非法关键词拦截

有的网站经常被恶意搜索&#xff0c;站长们不胜其烦。那我们如何屏蔽恶意搜索关键词呢&#xff1f;下面就随小编一起来解决这个问题吧。 后台设置预览图&#xff1a; 设置教程&#xff1a; 1、把以下代码添加至当前主题的 functions.php 文件中&#xff1a; add_action(admi…

I2C接口+高度集成的电源管理芯片(PMIC)-iML1942

电源管理芯片 - iML1942是一个高度集成的电源管理IC为TFT液晶面板。它具有完整的I2C接口来编程各种参数。该设备包括一个针对AVDD的电流模式升压调节器&#xff0c;一个针对VBK1的同步升压转换器。VGL可选的反相转换器或负电荷泵调节器&#xff0c;VSS1负线性调节器&#xff0c…

基于python的数据分解-趋势-季节性-波动变化

系列文章目录 前言 时间序列数据的分解&#xff0c;一般分为趋势项&#xff0c;季节变化项和随机波动项。可以基于加法或者乘法模型。季节变化呈现出周期变化&#xff0c;因此也叫季节效应(周期&#xff09;。 一、数据分解步骤 &#xff08;1&#xff09;估计时间序列的长期…

相关向量机RVM算法介绍继承sklearn-SVM-API实现回归预测算例

一、相关向量机RVM与支持向量机SVM对比 1、相关向量机&#xff08;RVM&#xff09; ①定义与原理 相关向量机&#xff08;Relevance Vector Machine, RVM&#xff09;是一种基于概率模型的机器学习算法&#xff0c;主要用于分类和回归分析。基于稀疏贝叶斯学习框架&#xff…

杰理科技AD142A语音芯片,语音玩具方案—云信通讯

语音玩具产品市场的需求量比较大&#xff0c;从前简单的发光玩具&#xff0c;到各种动作的电子玩具&#xff0c;再到如今的语音录音灯光动作玩具&#xff0c;可见玩具行业也是在不断地演变。 杰理语音芯片AD142A4的优势主要是支持录音、录变音、语音播放&#xff0c;广泛应用于…

kubernetes集群部署:node节点部署和CRI-O运行时安装(三)

关于CRI-O Kubernetes最初使用Docker作为默认的容器运行时。然而&#xff0c;随着Kubernetes的发展和OCI标准的确立&#xff0c;社区开始寻找更专门化的解决方案&#xff0c;以减少复杂性和提高性能。CRI-O的主要目标是提供一个轻量级的容器运行时&#xff0c;它可以直接运行O…

给我的 IM 系统加上监控两件套:【Prometheus + Grafana】

监控是一个系统必不可少的组成部分&#xff0c;实时&#xff0c;准确的监控&#xff0c;将会大大有助于我们排查问题。而当今微服务系统的话有一个监控组合很火那就是 Prometheus Grafana&#xff0c;嘿你别说 这俩兄弟配合的相当完美&#xff0c;Prometheus负责数据采集&…

手写实现一个ORM框架

手写实现一个ORM框架 什么是ORM框架、ORM框架的作用效果演示框架设计代码细节SqlBuilderSqlExecutorStatementHandlerParameterHandlerResultSetHandler逆序生成实体类 大家好&#xff0c;本人最近写了一个ORM框架&#xff0c;想在这里分享给大家&#xff0c;让大家来学习学习。…

10、matlab中字符、数字、矩阵、字符串和元胞合并为字符串并将字符串以不同格式写入读出excel

1、前言 在 MATLAB 中&#xff0c;可以使用不同的数据类型&#xff08;字符、数字、矩阵、字符串和元胞&#xff09;合并为字符串&#xff0c;然后将字符串以不同格式写入 Excel 文件。 以下是一个示例代码&#xff0c;展示如何将不同数据类型合并为字符串&#xff0c;并以不…

【设计模式】装饰器模式(定义 | 特点 | Demo入门讲解)

文章目录 定义装饰模式的结构 快速入门 | Demo顶层抽象DataSource数据源接⼝具体实现类引入BASE**64**编码装饰器客户端Client 定义 所谓装饰器模式其实就是在原有的功能上做一个增强&#xff01;&#xff01; 换句话说&#xff1a;以前你妈妈揍你的时候用的巴掌&#xff0c;但…

Android 简单快速实现 下弧形刻度尺(滑动事件)

效果图&#xff1a; 直接上代码&#xff1a; package com.my.view;import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Pai…

SQL注入【1】——通用漏洞/SQL注入/mysql跨库/ACCESS偏移

一、知识点: 1、脚本代码与数据库前置知识 2、Access数据库注入-简易&偏移 3、MYSQL数据库注入-简易:权限跨库 二、前置知识: &#xff08;一&#xff09;SQL注入漏洞产生原理分析 SQL注入产生条件&#xff1a;根本条件&#xff1a;可控变量、特定函数。 脚本代码在实现…