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

Java进阶—GC回收(垃圾回收)

1. 什么是垃圾回收

垃圾回收(Garbage Collection,GC)是Java虚拟机(JVM)的一项重要功能,用于自动管理程序中不再使用的内存。在Java中,程序员不需要手动释放内存,因为GC会自动检测并回收不再使用的对象,从而减少内存泄漏的风险。

2. 垃圾回收的空间

Java 的自动内存管理主要是针对对象内存的回收和对象内存的分配。同时,Java 自动内存管理最核心的功能是 堆内存中对象的分配与回收。
Java 堆是垃圾收集器管理的主要区域,因此也被称作 GC 堆(Garbage Collected Heap)。
从垃圾回收的角度来说,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆被划分为了几个不同的区域,这样我们就可以根据各个区域的特点选择合适的垃圾收集算法。
记住jdk8中的垃圾回收区域就好
在这里插入图片描述

3. 垃圾回收器的分类

3.1按实现方式分类

  1. 串行垃圾回收器(Serial GC):使用单个线程进行垃圾回收,适用于单核CPU环境。可以通过 -XX:+UseSerialGC 参数启用。
  2. 并行垃圾回收器(Paraller GC):使用多个线程同时进行垃圾回收,提高回收效率,适用于多核CPU环境。可以通过 -XX:+UseParallelGC 参数启用。
  3. 并发垃圾回收器(Concurrent GC):在应用程序运行的同事进行垃圾回收,减少停顿时间,提高响应性能。可以通过 -XX:+UseConcMarkSweepGC 参数启用。
  4. G1垃圾回收器(Garbage-First Garbage Collector):一种面向服务端应用的垃圾回收器,具有高吞吐量和地停顿时间的特点,适用于大内存应用。可以通过 -XX:+UseG1GC 参数启用。
  5. ZGC:一种低延迟的垃圾回收器,适用于需要更短停顿时间的应用场景。可以通过 -XX:+UseZGC 参数启用。

Java虚拟机的默认垃圾回收器随着Java版本和虚拟机的不同而有所变化。一般来说,在较早的Java版本中(如Java 8及之前的版本),默认的垃圾回收器是串行垃圾回收器(Serial GC),适用于单核CPU环境。

从Java 9开始,默认的垃圾回收器是G1垃圾回收器(Garbage-First Garbage Collector)。G1垃圾回收器是一种面向服务端应用的垃圾回收器,具有高吞吐量和低停顿时间的特点,适用于大内存应用。

3.2 按作用范围分类

  1. 新生代垃圾收集(Minor GC/Young GC):只对新生代进行垃圾回收。新生代一般使用复杂算法进行收集,将存货的对象复制到另一个区域,并清理掉原区域中的无用对象。因为新生代的对象生命周期较短,所以新生代的垃圾回收频率比较高。
  2. 老年代垃圾收集Major GC/Old GC):只对老年代进行垃圾收集。老年代一般使用标记-清除(Mark and Sweep)或者标记-整理(Mark and Compact)算法进行收集,清理掉不再使用的对象。老年代的垃圾回收相对较少,但由于老年代中存放着长期存活的对象,因此垃圾收集的效率和停顿时间会影响到整个应用的性能。
  3. 混合收集(Mixed GC):对整个新生代和部分老年代收集。混合收集通常是为了提高垃圾收集的效率,将部分老年代中的对象以一并清理掉,减少老年代的内存占用。
  4. 整堆收集(Full GC):收集整个Java堆和方法区。在有些语境中,Major GC也可以用来指代整堆收集。整堆收集通常发生在老年代空间不足或元空间(在Java 8及之后的版本中)空间不足时,或者在执行显式的System.gc()方法时。

这些不同的垃圾收集类型在不同的情况下会被JVM自动触发,以维护Java应用程序的内存使用和性能。

- 下面是触发不同类型垃圾回收的一些情况:

  1. 新生代收集(Minor GC / Young GC)
    • 当新生代中的Eden区满时,触发Minor GC。在Minor GC中,会将存活的对象复制到Survivor区,并清理掉Eden区和其中的无用对象。
    • 当Survivor区无法容纳所有存活的对象时,存活较长时间的对象会被移动到老年代,而不是进行Minor GC。
  2. 老年代收集(Major GC / Old GC)
    • 当老年代的空间不足以存放新分配的对象时,会触发Major GC。Major GC会清理老年代中的无用对象,以释放空间给新的对象使用。
    • 在并发标记-清除算法中,当老年代的内存使用达到一定阈值时,会触发并发标记,然后在空闲时进行垃圾回收。
  3. 混合收集(Mixed GC)
    • 混合收集通常在老年代垃圾回收的同时,对新生代也进行部分回收。这种方式可以更均衡地处理新生代和老年代的内存回收,提高整体性能。
  4. 整堆收集(Full GC)
    • 在老年代空间不足时,或者在永久代(在Java 8之前的版本中)或元空间(在Java 8及之后的版本中)空间不足时,会触发整堆收集。
    • 显式调用System.gc()方法时,也可能触发整堆收集,但并不保证一定会执行。

4. 堆中对象的生命周期

  1. 加载阶段:当程序使用new关键字创建一个对象时,该对象会被加载堆内存中。它通常会被分配到新生代的Eden区,有一种特殊情况,大对象会直接分配到老年区。

大对象(LargeObject)通常会直接分配到老年代。在Java中,大对象是指占用内存较大的对象,例如大数组或大集合。由于大对象占用的内存较大,将其分配到新生代可能会导致频繁的内存复制和回收,影响程序的性能。
G1 垃圾回收器会根据 -XX:G1HeapRegionSize 参数设置的堆区域大小和-XX:G1MixedGCLiveThresholdPercent 参数设置的阈值,来决定哪些对象会直接进入老年代。
Parallel Scavenge垃圾回收器中,默认情况下,并没有一个固定的阈值(XX:ThresholdTolerance是动态调整的)来决定何时直接在老年代分配大对象。而是由虚拟机根据当前的堆内存情况和历史数据动态决定。

  1. 存活阶段:在对象被加载到堆内存后,如果该对象仍然被引用着,则认为该对象处于存活状态。如果对象不再被任何引用引用,则认为该对象是垃圾,将在下一次垃圾回收时被回收。
    如果对象在新生代经过一次Minor GC后仍然存活,它将被移动到新生代的Survivor区。在Survivor区中经过多次存活后,对象可能被晋升到老年代。
    • 怎么判断对象进入老年代
      • 年龄判断:在新生代中,每个对象被创建时都会被赋予一个年龄计数器。经过一次Minor GC,如果对象仍然存活,它的年龄就会增加。当对象的年龄达到一定阈值时(通常是15),就会晋升到老年代。
      • Survivor空间不足:Survivor空间用来存放新生代中的存活对象。如果Survivor空间不足以容纳对象,那么这些存活对象会被直接晋升到老年代。
      • 空间分配担保:在进行Minor GC时,如果新生代中的对象无法全部晋升到老年代,但是老年代的剩余空间不足以存放新生代中的所有存活对象时,JVM会进行一次Full GC,确保能够为新生代中的对象分配足够的空间。

3.垃圾回收阶段:当对象不再被引用时,JVM的垃圾回收器会识别并回收这些对象所占用的内存。垃圾回收的具体时间取决于垃圾回收器的策略和堆的使用情况。

  • 怎么判断对象可以被回收
    • 引用计数器:引用计数器是一种简单的方法,它通过在对象上维护一个引用计数器来记录对象被引用的次数。当引用计数器为0时,表示对象不再被引用,可以被回收。然而,引用计数器无法处理循环引用的情况,因此在Java中并没有使用这种方法。

    • 可达性分析:Java使用可达性分析来判断对象是否不再被引用。可达性分析是从一组称为"GC Roots"的根对象开始,递归地遍历所有对象的引用关系,标记所有被引用的对象为存活对象,未被标记的对象则被认为是垃圾。这样,不再被引用的对象最终会被垃圾收集器回收。

    • 在Java中,GC Roots就是根集合,包括:

      • 虚拟机栈(Java Stack)中的引用对象,即局部变量和参数。
      • 方法区(Method Area)中的类静态属性引用的对象。
      • 方法区中常量引用的对象。
      • 本地方法栈(Native Method Stack)中JNI(Java Native Interface)引用的对象。
    • 如何判断一个常量是废弃常量?
      假如在字符串常量池中存在字符串 “abc”,如果当前没有任何 String 对象引用该字符串常量的话,就说明常量 “abc” 就是废弃常量,如果这时发生内存回收的话而且有必要的话,“abc” 就会被系统清理出常量池了。

    • 如何判断一个类是无用的类?
      正常很难满足这三个条件的。

      • 该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。
      • 加载该类的 ClassLoader 已经被回收。
      • 该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
  1. 终结阶段:在对象被回收之前,JVM会调用对象的finalize()方法进行清理和释放资源。但是,finalize()方法并不保证一定会被调用,因此不应该依赖于finalize()方法来释放资源。finalize()的调用时机是不确定的,不能保证一定会被调用
  2. 内存回收阶段:在垃圾回收阶段,如果对象经过finalize()方法后仍然未被引用,则会被回收,并释放其占用的内存空间。对于新生代的对象,会经过Minor GC;对于老年代的对象,会经过Major GC。

5. 对象的引用对垃圾回收的影响

  • 强引用、软引用、弱引用、虚引用
    在Java中,引用(Reference)是用来描述对象之间的关系的。Java提供了几种不同类型的引用,包括强引用、软引用、弱引用和虚引用,它们主要用于控制对象的可达性,从而影响垃圾回收的行为。
    1. 强引用(Strong Reference):强引用是最常见的引用类型。如果一个对象具有强引用,即使内存空间不足,垃圾收集器也不会回收这个对象。例如:

      Object obj = new Object(); // obj是一个强引用
    2. 软引用(Soft Reference):软引用用于描述那些还有用但并非必须的对象。在系统内存不足时,垃圾收集器会根据软引用的情况来决定是否回收对象。软引用可以通过java.lang.ref.SoftReference类来创建:

      SoftReference<Object> softRef = new SoftReference<>(new Object());

      例如,缓存中的对象可以使用软引用,当内存不足时,垃圾回收器可以根据软引用情况来回收缓存中的对象,从而释放内存。

    3. 弱引用(Weak Reference):弱引用比软引用更弱,只要垃圾回收器运行,无论内存是否足够,都会回收只被弱引用指向的对象。弱引用可以通过java.lang.ref.WeakReference类来创建:

      WeakReference<Object> weakRef = new WeakReference<>(new Object());

      弱引用通常用于实现一些缓存中的临时对象,可以随时被回收而不会占用太多内存。

    4. 虚引用(Phantom Reference):虚引用是所有引用中最弱的一种。一个持有虚引用的对象,和没有引用几乎是一样的,随时可能被垃圾回收器回收。虚引用主要用于在对象被回收时收到一个系统通知或执行一些清理操作。虚引用可以通过java.lang.ref.PhantomReference类来创建:

      ReferenceQueue<Object> queue = new ReferenceQueue<>();
      PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue);

      虚引用本身并不能阻止对象被回收,它的主要作用是在对象被回收时执行一些特定的操作,例如清理对象关联的资源或发送通知。
      以下是一个简单的示例,演示了如何使用虚引用和引用队列:

      import java.lang.ref.PhantomReference;
      import java.lang.ref.Reference;
      import java.lang.ref.ReferenceQueue;public class PhantomReferenceExample {public static void main(String[] args) {Object obj = new Object();ReferenceQueue<Object> queue = new ReferenceQueue<>();PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue);// 显示判断对象是否被回收System.out.println("Is object still alive? " + (phantomRef.get() != null));// 释放对象引用obj = null;// 强制垃圾回收System.gc();// 检查引用队列是否有引用对象Reference<?> refFromQueue = queue.poll();if (refFromQueue != null) {System.out.println("Object is in the queue.");} else {System.out.println("Object is not in the queue.");}}
      }

      在这个例子中,当对象被垃圾回收器回收时,phantomRef将会被添加到queue引用队列中,我们可以通过检查引用队列中是否有引用来判断对象是否被回收。

这些引用类型可以帮助开发人员更灵活地控制对象的生命周期和内存回收行为,特别是在处理大量数据或需要特定内存管理策略的情况下。

6. 垃圾回收算法

  1. 标记-清除(Mark and Sweep)算法
    标记-清除算法(Mark and Sweep Algorithm)是一种基本的垃圾回收算法,用于标记和清除不再被引用的对象。该算法分为两个阶段:标记阶段和清除阶段。

    • 标记阶段
      • 从根对象(如虚拟机栈中的引用对象、静态变量等)开始,遍历所有可以访问到的对象,并标记这些对象为活动对象。
      • 对于无法访问到的对象,即不可达对象,将其标记为待清除对象。
    • 清除阶段
      • 遍历堆内存中的所有对象,将标记为待清除的对象进行清除操作,即回收其所占用的内存。

    标记-清除算法的优点是简单高效,但也存在一些缺点:

    • 内存碎片问题:由于标记-清除算法会在清除阶段产生不连续的内存碎片,可能导致无法找到足够大的连续内存块来分配新对象。
    • 效率问题:标记和清除过程可能会耗费较长的时间,且在清除阶段会暂停应用程序的运行。
  2. 复制算法(Copying Algorithm)

    复制算法(Copying Algorithm)是一种垃圾回收算法,通常用于新生代的内存管理。它的核心思想是将内存空间分为两个大小相等的区域,通常称为"From"区和"To"区。在垃圾回收过程中,所有存活的对象都会被复制到"To"区,而非存活的对象则会被丢弃。
    复制算法的具体步骤如下:

    1. 初始分配:将新生代内存空间分为两个大小相等的区域,通常称为"From"区和"To"区。
    2. 新创建的对象首先会被分配到"From"区。
    3. 标记存活对象:从根对象开始,通过可达性分析标记所有存活的对象。
    4. 复制存活对象:将所有存活的对象复制到"To"区,同时按照对象的地址顺序依次排列,确保对象之间的地址是连续的。
    5. 更新引用:更新所有指向存活对象的引用,使其指向"To"区中的地址。
    6. 交换空间:将"From"区和"To"区的角色互换,使得下一次垃圾回收时仍然使用这两个区域,而不需要重新分配内存空间。

    复制算法的优点是简单高效,并且可以解决标记-清除算法中的内存碎片问题。但是,它也有一些缺点,主要是需要额外的内存空间来存储复制后的对象,以及在复制过程中需要暂停应用程序的运行。为了减少这些缺点,通常会将新生代划分为更多的存活区域,并使用"对象年龄"来决定何时将对象晋升到老年代。
    总结一下:
    可用内存变小:可用内存缩小为原来的一半。
    不适合老年代:如果存活对象数量比较大,复制性能会变得很差。

  3. 标记-整理算法(Mark-Sweep-Compact Algorithm)
    标记-整理算法(Mark-Sweep-Compact Algorithm)是一种垃圾回收算法,通常用于老年代的内存管理。它结合了标记-清除算法和内存整理的思想,用于解决标记-清除算法可能产生的内存碎片问题。
    标记-整理算法的主要步骤包括:

    1. 标记阶段:从根对象开始,通过可达性分析标记所有存活的对象。
    2. 清除阶段:遍历整个堆内存,将未被标记的对象清除,即回收其占用的内存空间。
    3. 整理阶段:将存活的对象向一端移动,使得所有存活对象在内存中连续排列,从而将内存空间合并为一个大的连续空间。

    标记-整理算法的优点是可以避免内存碎片问题,使得堆内存中的空闲空间更加连续,有利于提高内存分配的效率。但是,与复制算法相比,标记-整理算法需要更多的计算和移动操作,可能会影响应用程序的性能。因此,通常只在老年代等内存碎片严重的情况下使用。

相关文章:

Java进阶—GC回收(垃圾回收)

1. 什么是垃圾回收 垃圾回收(Garbage Collection&#xff0c;GC)是Java虚拟机(JVM)的一项重要功能&#xff0c;用于自动管理程序中不再使用的内存。在Java中&#xff0c;程序员不需要手动释放内存&#xff0c;因为GC会自动检测并回收不再使用的对象&#xff0c;从而减少内存泄…...

C++默认构造函数(二)

目录 构造函数补充 构造函数初始化列表的使用 赋值运算符重载函数 运算符重载函数介绍 运算符重载函数的使用 赋值运算符重载函数 赋值运算符重载函数的使用 拷贝构造函数和赋值运算符重载函数 重载前置和后置 前置 后置 重载流插入<<与流提取>> 流插…...

云原生部署手册02:将本地应用部署至k8s集群

&#xff08;一&#xff09;部署集群镜像仓库 1. 集群配置 首先看一下集群配置&#xff1a; (base) ➜ ~ multipass ls Name State IPv4 Image master Running 192.168.64.5 Ubuntu 22.04 LTS1…...

AJAX——JSON

目录 一、JSON概述 二、JSON对象语法 三、JSON序列化方法 四、JSON与XML比较 五、Java对象与Json对象的转换 六、Js解析服务器发送过来的JSON字符串 七、$.getJSON() 一、JSON概述 JSON简介:JSON的全称为JavaScript Object Nation(JavaScript 对象表示语法)&#xff0c;…...

Nexus3 Docker 私有仓库

Nexus3 Docker 私有仓库 安装并部署 Nexus3 $ docker search nexus3$ docker pull sonatype/nexus3$ mkdir /home/tester/data/docker/nexus3/sonatype-work $ sudo chown -R 200 /home/tester/data/docker/nexus3/sonatype-work$ docker run -d --namenexus3 \ --restartalw…...

Element UI el-dialog自由拖动功能

1.创建drag .js文件 /*** 拖拽移动* param {elementObjct} bar 鼠标点击控制拖拽的元素* param {elementObjct} target 移动的元素* param {function} callback 移动后的回调*/ export function startDrag(bar, target, callback) {var params {top: 0,left: 0,currentX: …...

RPC浅析,加密数据解析

个人总结 其实就是HOOK注入wbsocket 链接创建服务端和客户端进行通信&#xff0c;直接调用js代码中的加密方法 将结果通过浏览器客户端传入服务端。一种比较好实用的一种技术 https://blog.csdn.net/qq_36759224/article/details/123082574 &#xff08;搬运记录下&#xff…...

光速论文能用吗 #媒体#知识分享#学习方法

光速论文是一个非常有效的论文写作、查重降重工具&#xff0c;它的使用非常简单方便&#xff0c;而且功能强大&#xff0c;是每个写作者必备的利器。 首先&#xff0c;光速论文具有强大的查重降重功能&#xff0c;能够快速检测论文中的抄袭部分&#xff0c;帮助作者避免不必要的…...

智慧工地解决方案,智慧工地项目管理系统源码,支持大屏端、PC端、手机端、平板端

智慧工地解决方案依托计算机技术、物联网、云计算、大数据、人工智能、VR&AR等技术相结合&#xff0c;为工程项目管理提供先进技术手段&#xff0c;构建工地现场智能监控和控制体系&#xff0c;弥补传统方法在监管中的缺陷&#xff0c;最线实现项目对人、机、料、法、环的全…...

【前端寻宝之路】学习和使用label标签

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-2nm9oQQVtSL8hDS1 {font-family:"trebuchet ms",verdana,arial,sans-serif;f…...

项目————网络聊天室

服务器 #include <myhead.h> typedef struct msg{char flag;char name[20];char cont[128]; }msg_t;typedef struct link{struct sockaddr_in cin;struct link* next; }link_t;void do_login(int sfd,msg_t msg,link_t *L,struct sockaddr_in cin){link_t* pL;if(sendto…...

【计算机网络】基本概念

基本概念 IP 地址端口号协议协议分层封装分用客户端服务器请求和响应两台主机之间的网络通信流程 IP 地址 概念&#xff1a;IP 地址主要是用于唯一标识网络主机、其他网络设备&#xff08;如路由器&#xff09;的网络地址。简单来说&#xff0c;IP地址用来唯一定位主机。格式&…...

Redis入门到实战-第七弹

Redis实战热身Sets篇 完整命令参考官网 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的&#xff08;采用BSD许可证&#xff09;&#xff0c;用作数据库、缓存、消息代理和流…...

图像处理学习笔记(一)

本文主要介绍&#xff0c;以供读者能够理解该技术的定义、原理、应用。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;ISP处理 &#x1f380;CSDN主页 发狂的小花 &#x1f304;人生秘诀&#xff1a;学习的本质就…...

duckdb学习-1

DuckDB is a fast in-process analytical database DuckDB supports a feature-rich SQL dialect complemented with deep integrations into client APIs 在notebook中使用duckdb 安装 pip install duckdb 示例代码: #> pip install jupysql #> pip install duckdb-en…...

GEE高阶案例——Landsat/Sentinel/MODIS影像进行缨帽变换一行代码实现

本教程的主要目的是利用eemont中的tasseledCap()的函数进行缨帽变换实现。 在 eemont 中,可使用扩展到 ee.Image 和 ee.ImageCollection 对象的 tasseledCap 方法计算缨帽亮度、绿度和湿度组件。只需从支持的平台加载图像,然后使用 tasseledCap 添加分量带即可。 代码: !p…...

数独游戏(c++题解)

题目描述 给出一个的表格&#xff0c;部分格子已经填好数。请填完所有空白格子&#xff0c;使得表格每一行、每一列、每个的九宫格&#xff0c;都恰好填满这9个数字。 输入格式 9行9列的方阵状态&#xff0c;0代表空格。 输出格式 输出完成后的方阵状态&#xff0c;每一个…...

【开发方案】Android 应用双卡搜网功能

一、功能简介 需求:开机自动开始搜网并显示网络列表 那么就不能将相关类做成单例,不能将subId、phoneId等卡相关的属性作为UI、服务的全局变量。 二、流程设计 NetworkSelectReceiver:监听开机广播,触发拉起搜网服务 NetworkOperatorService:搜网服务,完成后调起用户…...

图论基础|深度优先dfs、广度优先bfs

dfs 与 bfs 区别 提到深度优先搜索&#xff08;dfs&#xff09;&#xff0c;就不得不说和广度优先搜索&#xff08;bfs&#xff09;有什么区别 先来了解dfs的过程&#xff0c;很多录友可能对dfs&#xff08;深度优先搜索&#xff09;&#xff0c;bfs&#xff08;广度优先搜索…...

Python从入门到精通秘籍十七

一、Python的构造方法 在Python中&#xff0c;构造方法是一个特殊的方法&#xff0c;用于创建和初始化类的实例。构造方法的名称是__init__()&#xff0c;它在创建对象时自动调用。 下面是一个示例代码来详细解释Python的构造方法&#xff1a; class Person:def __init__(se…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西&#xff0c;但是如果把三者放在一起&#xff0c;它们之间到底什么关系&#xff1f;又有什么联系呢&#xff1f;我不是很明白&#xff01;&#xff01;&#xff01; 就比如说&#xff1a; 沙箱&#…...

es6+和css3新增的特性有哪些

一&#xff1a;ECMAScript 新特性&#xff08;ES6&#xff09; ES6 (2015) - 革命性更新 1&#xff0c;记住的方法&#xff0c;从一个方法里面用到了哪些技术 1&#xff0c;let /const块级作用域声明2&#xff0c;**默认参数**&#xff1a;函数参数可以设置默认值。3&#x…...