JVM 垃圾回收机制深度解析(含图解)
JVM 垃圾回收机制深度解析(含图解)
一、垃圾回收整体流程
垃圾回收图解
二、垃圾对象判定算法
以下是对 JVM 垃圾回收机制的进一步细化,结合图解直观展示核心概念、算法流程及收集器工作原理:
2.1 引用计数法(Reference Counting)
原理:
-
计数器管理
- 每个对象内嵌一个引用计数器(Reference Counter)。
- 引用增加(如被赋值、作为参数传递) → 计数器+1。
- 引用失效(如变量置空、离开作用域) → 计数器-1。
-
回收条件
- 当计数器归零时,对象立即被标记为垃圾并回收。
循环引用问题: 无法处理循环引用(如对象 A 和 B 互相引用),导致内存泄漏。
场景描述:
对象A和B互相引用,导致两者的引用计数始终≥1,即使它们已不被其他对象引用,也无法被回收。后果:内存泄漏(Memory Leak)。
解决循环引用的常见方法
-
弱引用(Weak Reference)
弱引用不增加对象的引用计数(如Java的WeakReference、Python的weakref)。
-
手动断开引用
开发者需在代码中显式解除循环引用(易出错,不推荐)。
-
周期检测算法
定期运行垃圾回收器检测循环引用(如Python的gc模块)。
2.2 可达性分析(Reachability Analysis)
可达性分析示意图
原理:
从一组称为GC Roots的根对象出发,沿着引用链向下搜索,所有能被访问到的对象视为“存活”,未被访问的则判定为“不可达”对象,可被回收。
整体结构
外层是可达性分析的主流程,内嵌三色标记法的核心流程。
颜色标识统一:
白色:未处理或可回收对象(最终状态)
灰色:待处理对象(中间状态)
黑色 :已处理完成对象
红色边框:垃圾回收相关操作
关键流程节点
-
标记GC Roots: 从GC Roots(根对象如栈、静态变量等)出发,递归遍历所有可达对象,将其直接引用的堆对象标记为灰色,并加入灰色队列,作为标记的起点。
-
三色标记循环: 通过灰色队列迭代处理对象(白→灰→黑状态变化)。
- 取出灰色对象,遍历其引用的子对象;
- 若子对象为白色,标记为灰色并加入队列;
- 当前灰色对象标记为黑色;
- 重复直到灰色队列为空。”
-
回收阶段: 清除所有白色(未被标记/不可达)对象,释放内存。
颜色状态映射
存活对象标记流程:
GC Roots → 白色 → 灰色 → 遍历引用 → 黑色(完成)垃圾对象:
始终为白色 → 最终被回收
可达性分析的优势
-
解决循环引用问题
即使对象A和对象B互相引用,若它们无法从GC Roots到达,仍会被判定为垃圾。 -
高效性
通过引用链遍历,仅需处理存活对象,避免全堆扫描。
并发标记的挑战
在并发标记阶段(如CMS、G1回收器),用户线程可能修改对象引用,导致两种问题:
-
漏标(Missing Mark)
-
增量更新(Incremental Update)
若黑色对象新增对白色对象的引用,将该黑色对象重新标记为灰色(需重新扫描)。
-
原始快照(SATB)
记录标记开始时的对象引用关系,后续新增的引用关系视为“待处理”。
-
-
多标(Floating Garbage)
- 已标记为存活的对象被用户线程置为不可达(通常容忍到下次GC处理)。
GC Roots 包括:
1. 虚拟机栈(Java 栈)中的引用对象
来源: 方法执行时,栈帧中局部变量表存储的引用类型变量。
生命周期: 与方法调用绑定,方法结束后引用失效。
示例:
public void method() {Object obj = new Object(); // obj 是 GC Root// 方法执行期间,obj 引用的对象不会被回收
} // 方法结束后,obj 出栈,对象失去 GC Root 引用
2. 方法区中静态属性引用的对象
来源: 类的静态变量(static 字段)。
生命周期: 与类的生命周期相同,类卸载前始终存活。
示例:
public class MyClass {static Object staticObj = new Object(); // staticObj 是 GC Root
}
3. 方法区中常量引用的对象
来源: 字符串常量池(String Table)、类常量(final static)等。
示例:
public class Constants {public static final String NAME = "Doubao"; // "Doubao" 是 GC Rootpublic static final List<String> LIST = Collections.unmodifiableList(Arrays.asList("a", "b") // 列表对象是 GC Root);
}
4. 本地方法栈中 JNI 引用的对象
来源: Java 调用本地代码(如 C/C++)时,本地方法栈中保存的引用。
示例:
public native void nativeMethod(); // 本地方法可能持有对象引用,成为 GC Root
5. 其他特殊引用
- 活动线程(Active Threads):
Thread thread = new Thread(() -> {Object obj = new Object(); // obj 被线程栈引用,成为 GC Root// ...
});
thread.start();
- 类加载器(ClassLoader):
加载的类和静态变量。
- JVM 内部对象:
如系统类(java.lang.Class)、异常对象(ThreadDeath)等。
GC Roots 内存示意图
三、垃圾回收算法详解
3.1 标记 - 清除(Mark-Sweep)
步骤:
1. 标记: 在堆中遍历所有对象,找出内存中需要回收的对象,并且把它们标记出来。
(蓝色为存活对象、灰色为可回收对象、白色为可用内存)

2. 清除: 清除掉被标记需要回收的对象,释放出对应的内存空间。

缺点:
- 效率低: 两次遍历堆,耗时较长。
- 内存碎片: 回收后产生不连续内存块,可能导致大对象分配失败。
3.2 复制(Copying)
步骤:
- 将内存分为Eden 区和两个Survivor 区(通常比例 8:1:1)。
- 新对象分配到 Eden 区,当 Eden 区满时触发 Minor GC。
- 存活对象复制到 From Survivor (s0) 区,清空 Eden 区。
- 下次 GC 时,将 Eden+ From Survivor (s0) 的存活对象复制到 To Survivor (s1) 区,清空原区域。
- 经历多次 GC 仍存活的对象晋升到老年代。
图解:
- 将内存划分为两块相等的区域,每次只使用其中一块
(蓝色为存活对象、灰色为可回收对象、白色为可用内存、绿色为保留内存)

3. 当其中一块内存使用完了,就将还存活的对象复制到另外一块上面,然后把已经使用过的内存空间一次清除掉。

优点: 无内存碎片,效率高(只需移动指针)。
缺点: 浪费 50% 内存空间(实际采用 8:1:1 比例,仅浪费 10%)。
3.3 标记 - 整理(Mark-Compact)
步骤:
- 标记: 遍历标记存活对象(灰色)。
- 整理: 将存活对象向一端移动,直接清理边界外的内存(白色区域)。
- 优点: 无内存碎片,适合对象存活率高的场景(如老年代)。
图解:
- 标记过程仍然与 标记-清除算法 一样,但是后续步骤不是直接对可回收对象进行清理,
而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
(蓝色为存活对象、灰色为可回收对象、白色为可用内存)

- 让所有存活的对象都向一端移动,清理掉边界以外的内存。

缺点: 需移动对象,成本较高。
3.4 分代收集(Generational Collection)
原理:
根据对象存活周期将堆分为新生代和老年代:
- 新生代(Eden+Survivor): 对象存活率低,采用 复制算法。
- 老年代: 对象存活率高,采用 标记 - 清除 或 标记 - 整理算法 。
- 永久代 / 元空间: 存储类信息、常量池等,GC 频率低。
四、垃圾收集器详解
以下是 Java 主流垃圾回收器的核心启动参数及典型配置
按 分代收集器 和 分区收集器 分类整理:
I、分代收集器
4.1 Serial 收集器
特点: 单线程,STW(Stop The World)【全程暂停用户应用程序】,采用复制算法。
算法:
-
新生代:复制算法(Copying)
将存活对象从Eden区和Survivor区复制到另一个Survivor区,清除未存活对象。 -
老年代:标记-整理算法(Mark-Compact)
标记存活对象后,整理内存空间,消除碎片。
适用场景:
单线程环境(Client 模式),客户端模式或小内存应用。
参数:
# 新生代和老年代均使用Serial(单线程)
-XX:+UseSerialGC -Xmx512m
4.2 Parallel Scavenge 收集器(吞吐量优先)
特点: 多线程,关注吞吐量(运行用户代码时间 / 总时间)。
算法:
-
新生代(Parallel Scavenge):复制算法
多线程并行复制存活对象,提升回收效率。 -
老年代(Parallel Old):标记-整理算法
多线程并行标记和整理,减少碎片。
适用场景:
多核服务器,注重吞吐量而非低延迟。
参数:
# 新生代Parallel Scavenge + 老年代Parallel Old
-XX:+UseParallelGC -XX:+UseParallelOldGC -Xmx4g # 控制最大停顿时间(毫秒)
-XX:MaxGCPauseMillis=100 # 控制吞吐量目标(默认99%)(如 99 表示 1% 时间用于 GC)。
-XX:GCTimeRatio=99# 自适应调整内存区域大小
-XX:+UseAdaptiveSizePolicy
4.3 CMS(Concurrent Mark Sweep)收集器(低延迟)
算法:
- 标记-清除算法(Mark-Sweep)
- 工作流程:
1. 初始标记(STW,短暂):标记 GC Roots 直接关联的对象。
2. 并发标记:与用户线程并发执行,遍历可达对象。
3. 重新标记(STW):修正并发标记阶段因用户线程运行导致的对象引用变化(使用增量更新算法)。
4. 并发清除:与用户线程并发未标记对象。
缺点:
-
内存碎片: 标记-清除算法不整理内存,长期运行后碎片化严重,可能导致:
-
晋升失败(Promotion Failed): 新生代对象无法晋升到老年代。
-
大对象分配失败(Humongous Allocation Failure)。
-
最终触发 Full GC,使用 Serial Old(标记-整理算法) 压缩内存。
CMS的核心目标是通过标记-清除算法减少垃圾回收的停顿时间(STW)。然而,由于其设计上的限制,CMS在某些场景下触发Full GC,无法通过并发操作完成垃圾回收,此时JVM会触发故障回退机制(Fallback Mechanism),强制使用单线程的Serial Old收集器(标记-整理算法)进行压缩执行Full GC以恢复内存可用性。这种设计是CMS在低延迟与内存连续性之间的权衡。
-
-
吞吐量下降: 并发阶段占用 CPU 资源,与用户线程竞争。
-
无法处理突发分配压力: 并发周期中若老年代空间不足,触发并发模式失败(Concurrent Mode Failure)。
| 触发Full GC的场景 | 描述 | 是否使用Serial Old |
|---|---|---|
| 并发模式失败 | 并发标记期间老年代空间不足 | 是 |
| 晋升失败 | 新生代对象晋升到老年代时因碎片无法分配 | 是 |
| 显式调用System.gc() | 强制触发Full GC(默认开启ExplicitGCInvokesConcurrent可绕过此行为) | 是 |
| 元空间耗尽 | 类元数据区无法扩展 | 是 |
| 其他内存分配失败 | 直接内存(Direct Memory)或本地内存(Native Memory)耗尽等 | 是 |
适用场景:
Web 服务器、需要快速响应的应用、老年代垃圾回收、追求低停顿时间。
参数:
# 新生代ParNew + 老年代CMS
-XX:+UseConcMarkSweepGC -Xmx8g # 老年代使用70%时触发CMS(默认92%)
-XX:CMSInitiatingOccupancyFraction=70# 控制Full GC时是否进行内存压缩(减少碎片)(标记-整理)。
-XX:+UseCMSCompactAtFullCollection# 并行执行重新标记阶段
-XX:+CMSParallelRemarkEnabled# 指定经过多少次Full GC后执行一次压缩(0表示每次Full GC都压缩)。
-XX:CMSFullGCsBeforeCompaction=0
II、分区收集器
4.4 G1(Garbage-First)收集器(区域化、平衡延迟与吞吐量)
算法:
-
分区(Region)
将堆划分为多个大小相等的 Region(如 2MB-32MB)。 -
新生代:复制算法
存活对象复制到Survivor Region或晋升到老年代Region。 -
老年代:标记-整理算法
并发标记后,优先回收垃圾最多的Region(Garbage-First),并整理Region内空间。 -
动态分代
每个 Region 可动态扮演 Eden、Survivor、Old 或 Humongous(大对象)。 -
可预测停顿
根据 Region 的回收价值(垃圾占比)排序,优先回收收益高的区域。 -
工作流程
1. 初始标记(STW 极短): 标记 GC Roots 直接关联的 Region。
2. 并发标记: 与用户线程并发标记存活对象。
3. 最终标记(STW): 处理并发阶段的增量更新(使用 SATB 快照算法)。
4. 筛选回收(STW): 根据停顿时间目标选择 Region 进行回收,采用复制算法。
关键说明:
G1 设计上通过 Mixed GC(混合回收) 避免 Full GC,但在极端情况(如并发标记失败)下仍可能触发 Full GC,此时 触发故障回退机制(Fallback Mechanism) 到单线程的 Serial Old收集器(标记-整理算法)。
- 触发条件: 堆内存不足且无法通过 Mixed GC 回收足够空间。
- 优化建议: 通过 -XX:G1ReservePercent 增加预留内存,降低 Full GC 概率。
适用场景:
大堆内存(数十GB至数百GB)、追求低延迟与吞吐量平衡的应用。
参数:
# 启用G1收集器(JDK 9+默认)
-XX:+UseG1GC -Xmx16g# 设置最大停顿时间目标(毫秒)
-XX:MaxGCPauseMillis=200# 设置Java堆区域大小(默认2的幂,1-32MB)
-XX:G1HeapRegionSize=8m# 老年代占用50%时启动混合回收
-XX:InitiatingHeapOccupancyPercent=50
# G1 垃圾收集器预留堆内存的百分比,默认值:10(即预留 10% 的堆内存)
-XX:G1ReservePercent=10
4.5 ZGC收集器(Z Garbage Collector)(超低延迟,JDK 11+)
特点:
-
着色指针(Colored Pointers)
将 GC 信息(Marked0/1、Remapped)存储在指针的低 4 位,无需扫描对象头。 -
读屏障(Load Barrier)
在读取对象引用时动态修正指针,实现并发移动。 -
并发整理
全程几乎无 STW(仅初始标记和再标记有极短停顿,通常 < 1ms)。
适用场景:
超大堆内存(TB 级),追求极致低延迟(<10ms),如金融交易系统。
算法:
-
并发标记-整理算法(Concurrent Mark-Compact)
1. 并发标记: 利用染色指针(Colored Pointers)标记对象状态。
2. 并发预备重分配: 确定需要清理的内存区域。
3. 并发重分配: 将存活对象复制到新地址,并更新引用。
4. 并发重映射: 修复旧地址到新地址的映射。
5. 关键技术: 染色指针和读屏障,支持全阶段并发执行。
参数:
# 启用ZGC(需JDK 11+)
-XX:+UseZGC -Xmx32g # 设置最大堆大小(ZGC适合大内存)
-Xmx64g -Xms64g# 设置并发GC线程数(默认CPU核心数的1/4)
-XX:ConcGCThreads=4# 配置GC周期的最大停顿时间(目标值)
-XX:MaxGCPauseMillis=10
4.6 Shenandoah收集器(超低延迟,OpenJDK 12+)
特点:
- 与 ZGC 类似,基于转发指针和布鲁姆过滤器实现并发回收,停顿时间极短。
适用场景:
OpenJDK 环境下的超大堆内存(TB级)、极低停顿时间(亚毫秒级)、低延迟应用。
算法:
-
并发复制算法(Concurrent Copying)
1. 并发标记: 与用户线程并发标记存活对象。
2. 并发预清理: 确定需要回收的Region。
3. 并发转移: 在用户线程运行时,将存活对象复制到新Region。
4. 引用更新: 并发更新对象引用至新地址。
5. 关键技术: 使用 读屏障(Read Barrier) 实现并发对象移动。
参数:
# 启用Shenandoah(需JDK 12+,OpenJDK默认包含)
-XX:+UseShenandoahGC -Xmx16g # 设置GC策略(normal/size/reference-time)
-XX:ShenandoahGCHeuristics=normal# 设置最大停顿时间目标(毫秒)
-XX:MaxGCPauseMillis=100
III、垃圾收集器对比表
| 收集器 | 新生代算法 | 老年代算法 | Full GC 收集器 | JDK版本支持 | 默认收集器(JDK版本) | 推荐堆大小 | 吞吐量 | 适用场景 | 是否开源 | 所属JVM实现 | 垃圾对象判定算法 | 核心特点 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Serial | 复制 | 标记-整理 | Serial Old(标记-整理) | JDK 1.0+ | JDK 1.0~8(客户端模式) | <512MB | 低 | 客户端应用、嵌入式系统 | 是 | HotSpot | 可达性分析(迭代标记) | 单线程简单高效,无多线程开销 |
| Parallel | 复制 | 标记-整理 | Parallel Old(标记-整理) | JDK 1.4+ | JDK 8(服务器模式) | 512MB~32GB | 高 | 批处理、计算密集型任务 | 是 | HotSpot | 可达性分析(并行标记) | 多线程并行回收,最大化吞吐量 |
| CMS | 复制(ParNew) | 标记-清除 | Serial Old(标记-整理) | JDK 1.5~JDK14 (JDK 9+ 标记为废弃,JDK 14+ 移除) | 无(需手动启用) | 512MB~4GB | 中 | 低延迟Web服务(中小堆) | 是 | HotSpot | 可达性分析(三色标记 + 增量更新) | 低延迟,并发标记减少停顿,但需监控碎片问题 |
| G1 | 复制 | 标记-整理(分Region) | Serial Old(标记-整理) | JDK 7u4+ | JDK 9+(服务器模式) | 4GB~64GB | 中~高 | 大堆内存、平衡型应用 | 是 | HotSpot | 可达性分析(三色标记 + SATB快照) | 分区回收,可预测停顿,自动整理碎片 |
| ZGC | 并发复制 | 并发标记-整理 | 无(无 Full GC 概念) | OpenJDK 11+ | JDK 15+(可选) | ≥4GB | 中 | 超大堆、亚毫秒级停顿 | 是 | HotSpot | 可达性分析(并发三色标记 + 染色指针) | 超大堆,染色指针,停顿<1ms |
| Shenandoah | 并发复制 | 并发复制 | 无(无 Full GC 概念) | OpenJDK 12+ | 无(需手动启用) | ≥4GB | 中 | 超大堆、极低延迟需求 | 是 | HotSpot | 可达性分析(并发三色标记 + 读屏障) | 全堆并发,停顿<10ms |
IIII、垃圾对象判定算法详解
| 收集器 | 判定算法实现 |
|---|---|
| Serial | 递归遍历GC Roots,标记可达对象(无并发优化)。 |
| Parallel | 多线程并行遍历GC Roots,标记可达对象。 |
| CMS | 三色标记法 + 增量更新(将修改引用的黑色对象重新标记为灰色)。 |
| G1 | 三色标记法 + SATB(原始快照)(基于标记开始时的引用关系进行标记)。 |
| ZGC | 并发三色标记法 + 染色指针(通过指针元数据记录对象状态)。 |
| Shenandoah | 并发三色标记法 + 读屏障(拦截对象访问,处理并发标记中的引用变化)。 |
五、GC 日志分析与可视化工具
5.1 典型 GC 日志示例
[GC (Allocation Failure) [PSYoungGen: 524288K->1024K(524288K)] 524288K->1025K(1048576K), 0.0012345 secs]
解析:
- GC:新生代 GC。
- Full GC:整堆 GC。
- Allocation Failure:因内存分配失败触发 GC。
- PSYoungGen:Parallel Scavenge 收集器的新生代。
- 524288K->1024K:回收前→回收后的内存使用量。
- 0.0012345 secs:GC 耗时。
5.2 可视化工具推荐
- GCViewer:解析 GC 日志,生成可视化图表(如停顿时间、内存使用趋势)。
- GCEasy:在线工具,上传 GC 日志后提供详细分析报告和优化建议。
- JProfiler:集成 GC 分析功能,支持实时监控和堆转储分析。
- Java Mission Control (JMC):Oracle 官方工具,提供高性能监控和诊断。
- Arthas(阿尔萨斯):阿里巴巴开源的 实时诊断工具,通过命令行或 Web UI 动态监控和排查问题。
- VisualVM:轻量级可视化工具,集成多种性能分析功能(含 GC 监控),支持插件扩展。
六、性能调优实战案例
6.1 高并发 Web 应用调优
场景: 8 核 16GB 服务器,Tomcat 应用,响应时间敏感。
配置:
java -Xms8g -Xmx8g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=100 \
-XX:G1HeapRegionSize=8m \
-XX:+ParallelRefProcEnabled \
-jar app.jar
效果:
- 新生代 GC 频率降低,停顿时间控制在 50ms 以内。
- 老年代碎片化问题缓解,Full GC 频率从每天数次降为每周一次。
6.2 大数据批处理调优
场景: Spark 作业,64GB 内存,追求高吞吐量。
配置:
spark-submit --conf spark.executor.memory=48g \
--conf spark.executor.extraJavaOptions="-XX:+UseParallelGC -XX:GCTimeRatio=99" \
--class com.example.BatchJob app.jar
效果:
- 吞吐量提升 20%,GC 时间占比从 5% 降至 1%。
- 并行 GC 充分利用多核 CPU,减少 STW 时间。
七、总结与最佳实践
垃圾判定:优先使用可达性分析,避免引用计数法的循环引用问题。
算法选择:
- 新生代:对象存活率低→复制算法。
- 老年代:对象存活率高→标记 - 整理算法。
收集器选型:
- 小内存 / 单线程:Serial。
- 吞吐量优先:Parallel。
- 低延迟:CMS(老年代)、G1(大内存)、ZGC/Shenandoah(超大内存)。
性能监控:
- 定期分析 GC 日志,监控停顿时间和内存使用趋势。
- 使用可视化工具定位内存泄漏和大对象问题。
通过结合图解和实战案例,可更直观地理解 JVM 垃圾回收机制的底层原理,从而针对性地优化应用性能。
附:
- JVM图解
- ⚙️运行时数据区的初始化时机
| 运行时数据区 | 初始化时机 | 与类加载的关系 |
|---|---|---|
| 方法区 | JVM 启动时分配内存,类加载时写入类元信息、常量池、静态变量等。 | 类加载的初始化阶段会向方法区写入静态变量。 |
| 堆 | JVM 启动时分配内存,对象实例在 new 时创建。 | 类初始化完成后,通过 new 触发对象分配。 |
| 虚拟机栈 | 线程创建时初始化,每个线程有独立栈空间,栈帧在方法调用时动态生成。 | 与类加载无关,由线程执行引擎管理。 |
| 程序计数器 | 线程创建时初始化,记录当前执行指令地址。 | 与类加载无关,由线程执行引擎管理。 |
| 本地方法栈 | 线程创建时初始化,存储本地方法(Native Method)调用信息。 | 与类加载无关,由本地方法接口(JNI)管理。 |
- 类加载与运行时数据区的关系
相关文章:
JVM 垃圾回收机制深度解析(含图解)
JVM 垃圾回收机制深度解析(含图解) 一、垃圾回收整体流程 垃圾回收图解 #mermaid-svg-KPtxlwWntQx8TOj3 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-KPtxlwWntQx8TOj3 .error-icon{fill…...
如何利用 Conda 安装 Pytorch 教程 ?
如何利用 Conda 安装 Pytorch 教程 ? 总共分为六步走: (1)第一步:验证conda 环境是否安装好? 1) conda -V2) conda --version(2)第二步:查看现有环境 conda env list…...
【ffmpeg】SPS与PPS的概念
PPS(Picture Parameter Set)详解 PPS(图像参数集)是H.264/H.265视频编码标准中的关键数据结构,与SPS(序列参数集)共同组成视频的解码配置信息,直接影响视频的正确解码和播放。以下是…...
uniapp vue 开发微信小程序 分包梳理经验总结
嗨,我是小路。今天主要和大家分享的主题是“uniapp vue 开发微信小程序 分包梳理经验总结”。 在使用 UniAppvue框架开发微信小程序时,当项目比较大的时候,经常需要分包加载。它有助于控制主包的大小,从而提升小程序的启…...
什么是VR展示?VR展示的用途
随着科技的迅猛发展,我们步入一个全新的数字时代。在这个时代,虚拟现实(VR)技术崭露头角,逐步改变我们对世界的认知。全景展示厅作为VR技术与传统展览艺术的完美结合,以独特的全景视角,引领我们…...
.NET外挂系列:4. harmony 中补丁参数的有趣玩法(上)
一:背景 1. 讲故事 前面几篇我们说完了 harmony 的几个注入点,这篇我们聚焦注入点可接收的几类参数的解读,非常有意思,在.NET高级调试 视角下也是非常重要的,到底是哪些参数,用一张表格整理如下ÿ…...
Go语言中new与make的深度解析
在 Go 语言中,new 和 make 是两个用于内存分配的内置函数,但它们的作用和使用场景有显著区别。 理解它们的核心在于: new(T): 为类型 T 分配内存,并将其初始化为零值,然后返回一个指向该内存的指针 (*T)。make(T, ar…...
3、ubantu系统 | 通过vscode远程安装并配置anaconda
1、vscode登录 登录后通过pwd可以发现目前位于wangqinag账号下,左侧为属于该账号的文件夹及文件。 通过cd ..可以回到上一级目录,通过ls可以查看当前目录下的文件夹及文件。 2、安装 2.1、下载anaconda 通过wget和curl下载未成功,使用手动…...
【Unity】 HTFramework框架(六十五)ScrollList滚动数据列表
更新日期:2025年5月16日。 Github 仓库:https://github.com/SaiTingHu/HTFramework Gitee 仓库:https://gitee.com/SaiTingHu/HTFramework 索引 一、ScrollList滚动数据列表二、使用ScrollList1.快捷创建ScrollList2.ScrollList的属性3.自定义…...
深度学习之用CelebA_Spoof数据集搭建一个活体检测-用MNN来推理时候如何利用Conan对软件包进行管理
我为什么用Conan 前面的文章:深度学习之用CelebA_Spoof数据集搭建一个活体检测-训练好的模型用MNN来推理有提到怎么使用MNN对训练好的模型进行推理,里面并没有提到我是怎么编译和进行代码依赖包的管理的详细步骤,在这里我是用的是Conan:一个C/C++包管理器,可以管理项目依赖…...
React 常见的陷阱之(如异步访问事件对象)
文章目录 前言1. 异步访问事件对象问题解决方案 2. 事件传播的误解**问题**解决方案 **3. 事件监听器未正确卸载****问题****解决方案** **4. 动态列表中的事件绑定****问题****解决方案** **5. 第三方库与 React 事件冲突****问题****解决方案** **6. 表单输入与受控组件****问…...
Swagger在java的运用
Swagger 是一个广泛使用的工具,用于设计、构建、记录和使用 RESTful Web 服务。它通过提供交互式的 API 文档、客户端 SDK 生成和 API 发现功能,极大地简化了 API 的开发和使用过程。以下是对 Swagger 的详细介绍,包括它的功能、使用场景、如…...
代码随想录算法训练营 Day49 图论Ⅰ 深度优先与广度优先
图论 基础 图的概念 图的概念 概念清单有向图 (a)无向图 (b)有向/无向如图 a 所示每条边有指向如图 b 所示每条边没有箭头指向权值每条边的权值每条边的权值度-有几条边连到该节点 (eg V 2 V_2 V2 度为 3)入度/出度出度:从该节点出发的边个数入度:…...
.NET外挂系列:1. harmony 基本原理和骨架分析
一:背景 1. 讲故事 为什么要开这么一个系列,是因为他可以对 .NET SDK 中的方法进行外挂,这种技术对解决程序的一些疑难杂症特别有用,在.NET高级调试 领域下大显神威,在我的训练营里也是花了一些篇幅来说这个…...
HarmonyOS NEXT端云一体化工程目录结构
视频课程学习报名入口:HarmonyOS NEXT端云一体化开发 端云一体化开发工程由端开发工程(Application)和云开发工程(CloudProgram)两大核心模块构成。 1)端开发工程目录结构 端开发工程主要用于开发应用端侧的业务代码,通用云开发模板的端开发工程目录结构如下图所示: …...
Ajax研究
简介 AJAX Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。 AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。 Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用…...
学习 Android(十)Fragment的生命周期
简介 Android 的 Fragment 是一个具有自己生命周期的 可重用 UI 组件,能够在运行时灵活地添加、移除和替换,从而支持单 Activity 多界面、动态布局和响应式设计。掌握 Fragment 的生命周期有助于正确地在各个阶段执行初始化、资源绑定、状态保存与释放操…...
flutter 常用组件详细介绍、屏幕适配方案
一、常用组件 1.基础组件 组件说明示例Text显示文本Text(‘Hello Flutter’, style: TextStyle(fontSize: 20))Image显示图片Image.network(‘https://example.com/image.jpg’)Icon显示图标Icon(Icons.home, size: 30, color: Colors.blue)RaisedButton / ElevatedButton按钮…...
Elasticsearch生产环境性能调优指南
#作者:朱雷 文章目录 一、背景二、优化项2.1. 磁盘优化2.2.配置文件优化2.3. jvm 配置2.4. 关闭或禁用 swap2.5. 最大文件描述符2.6. 段合并流量设置2.7. thread_pool相关 三、总结 一、背景 Elasticsearch是基于Lucene的开源分布式搜索与分析引擎,支持…...
野火鲁班猫(arrch64架构debian)从零实现用MobileFaceNet算法进行实时人脸识别(一)conda环境搭建
先安装miniconda wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh chmod x Miniconda3-latest-Linux-aarch64.sh bash Miniconda3-latest-Linux-aarch64.sh source ~/.bashrc conda --version按照MobileFaceNet的github官方指南,需要…...
RT Thread FinSH(msh)调度逻辑
文章目录 概要FinSH功能FinSH调度逻辑细节小结 概要 RT-Thread(Real-Time Thread)作为一款开源的嵌入式实时操作系统,在嵌入式设备领域得到了广泛应用。 该系统不仅具备强大的任务调度功能,还集成了 FinSH命令行系统,…...
Kotlin 极简小抄 P9 - 数组(数组的创建、数组元素的访问与修改、数组遍历、数组操作、多维数组、数组与可变参数)
Kotlin 概述 Kotlin 由 JetBrains 开发,是一种在 JVM(Java 虚拟机)上运行的静态类型编程语言 Kotlin 旨在提高开发者的编码效率和安全性,同时保持与 Java 的高度互操作性 Kotlin 是 Android 应用开发的首选语言,也可…...
CSS display有几种属性值
在 CSS 中,display 属性是控制元素布局和渲染方式的核心属性之一。它有多种属性值,每个值都决定了元素在文档流中的表现形式。以下是 display 的主要属性值分类及说明: 1. 块级和行内布局 块级元素 (block) 特性:独占一行&…...
【后端】【UV】【Django】 `uv` 管理的项目中搭建一个 Django 项目
🚀 一步步搭建 Django 项目(适用于 uv pyproject.toml 项目结构) 🧱 第 1 步:初始化一个 uv 项目(如果还没建好) uv init django-project # 创建项目,类似npm create vue⚙️ 第 …...
单片机设计_四轴飞行器(STM32)
四轴飞行器(STM32) 想要更多项目私wo!!! 一、系统简介 四轴飞行器是一种通过四个旋翼产生的升力实现飞行的无人机,其核心控制原理基于欧拉角动力学模型。四轴飞行器通过改变四个电机的转速来实现六自由度控制(前后、左右、上下…...
kafka配置SASL_PLAINTEXT简单认证
Kafka ZooKeeper 开启 SASL_PLAINTEXT 认证(PLAIN机制)最全实战教程 💡 本教程将手把手教你如何为 Kafka 配置基于 SASL_PLAINTEXT PLAIN 的用户名密码认证机制,包含 Kafka 与 ZooKeeper 的全部配置,适合入门。 &…...
PostgreSQL简单使用
一、PostgreSQL概念 特点 开源与自由 标准符合性 数据类型丰富 事务与并发 扩展性 安全性 优势 高性能 高可用性 灵活性 社区支持 成本效益 PostgreSQL结构 多层逻辑结构 第一层:实例(xxx.xxx.xxx.xxx…...
【Spring Boot】配置实战指南:Properties与YML的深度对比与最佳实践
目录 1.前言 2.正文 2.1配置文件的格式 2.2properties 2.2.1基础语法 2.2.2value读取配置文件 2.2.3缺点 2.3yml 2.3.1基础语法 2.3.2配置不同数据类型 2.3.3配置读取 2.3.4配置对象和集合 2.3.5优缺点 2.4综合练习:验证码案例 2.4.1分析需求 2.4.2…...
算法优选系列(9.BFS 解决拓扑排序)
目录 拓扑排序简介: 编辑 课程表(medium): 课程表II(medium): 火星词典(hard): 拓扑排序简介: 有向无环图(DAG图) 如上图每条边…...
(1)Java 17/18/19 新特性面试题
Java 17/18/19 新特性面试题 🚀 掌握前沿技术,成为顶尖 Java 工程师 1️⃣ Java 17/18/19 新特性价值点 👉 点击展开题目 Java 17/18/19新特性中,你认为最有价值的是哪些?请结合实际场景说明 密封类(Sealed Classes…...
