热修复的核心目标是在**不发布新版本、不重新安装、不重启应用(或仅轻量级重启)**的情况下,修复线上应用的 Bug 或进行小范围的功能更新,极大地提升用户体验和问题响应速度。

一、热修复的核心原理

无论哪种方案,其核心思想都是绕过 Android 系统的安装流程(APK 签名验证、Dex 优化、资源编译等),在运行时动态修改或替换有问题的代码、资源或 So 库。主要涉及以下几个关键技术点:

  1. 类加载机制 (ClassLoader):

    • Android 使用 PathClassLoader(主 APK)和 DexClassLoader(加载额外 Dex/Jar)来加载类。
    • 关键点在于 DexPathList 中的 dexElements 数组。类加载遵循双亲委托模型,当需要加载一个类时,会按顺序遍历 dexElements 数组中的 Dex 文件,直到找到目标类。
    • 热修复原理: 将包含修复后类的 Dex 文件(补丁包)插入到 dexElements 数组的最前面。这样,在加载目标类时,系统会先找到补丁 Dex 中的修复类并加载,从而覆盖原 APK 中 bug 类的加载。这是大部分 Dex 替换方案(如 Tinker, QZone)的基础。
  2. 资源修复:

    • Android 资源管理通过 AssetManagerResources 完成。每个 APK 在安装时都会生成一个唯一的资源 ID (packageId) 和编译后的资源表 (resources.arsc)。
    • 直接替换 resources.arsc 或资源文件通常不可行,因为 packageId 不匹配。
    • 热修复原理:
      • 创建新 AssetManager: 创建一个新的 AssetManager 实例,先加载补丁资源包(通常是一个单独的 APK 或资源压缩包),然后再加载原 APK 的资源路径。调用 AssetManager.addAssetPath(path)
      • 替换 Resources: 用这个新的 AssetManager 创建一个新的 Resources 实例,并替换掉 ApplicationActivityContext 持有的 Resources 引用(通过反射或接口方式)。
      • 资源 ID 冲突处理: 确保补丁包中的资源 ID 与主 APK 一致(通常在编译补丁时通过固定资源 ID 或公共库实现)。Sophix 采用了更复杂的运行时资源合并策略。
  3. So 库修复:

    • 本地库(.so)由 System.loadLibrary() 加载到进程的 Native 内存空间。
    • 直接覆盖已加载的 So 库非常困难,因为内存映射和符号绑定问题。
    • 热修复原理:
      • 重启后加载: 最稳妥的方式。将补丁 So 库文件下载到应用私有目录(如 libs),在应用下次启动时(或轻量级重启后),修改 java.library.path 或使用 DexClassLoader 的 Native 库路径参数,优先加载补丁目录下的 So 库。需要确保补丁 So 的 ABI 兼容性。
      • dlopen 替换 (高风险): 少数方案尝试在运行时使用 dlopen 重新加载补丁 So 并替换函数指针(如 AndFix 的 Native 方法替换原理的延伸),但这极其复杂,兼容性极差,且容易导致崩溃,不被主流方案采用。

二、主流热修复方案深度分析

以下是对几种代表性方案的深度剖析,涵盖原理、实现、优缺点及适用场景:

  1. Dex 插桩/类替换方案 (代表:QZone / Nuwa / 早期 Tinker 核心)

    • 原理: 利用类加载机制。
      • 在编译时,通过字节码插桩(Transform API / ASM)在所有类的构造函数或特定方法(如 Application.attachBaseContext)中插入一段对某个“空”工具类的引用(称为“插桩类”)。
      • 线上出现 Bug 时,生成一个补丁 Dex。这个 Dex 包含两个部分:1) 修复后的业务类; 2) 那个“空”工具类的真正实现类(其中包含加载补丁 Dex 的逻辑)。
      • 应用启动时,默认加载的 APK 中只有“空”工具类的桩(Stub)。当代码执行到引用该工具类的地方时,触发类加载。
      • 在工具类的 <clinit>(类初始化)方法中,通过反射获取 PathClassLoaderDexPathList 中的 dexElements 数组。
      • 将补丁 Dex 文件(已下载到本地)封装成一个 Element 对象,并插入到 dexElements 数组的最前面
      • 后续加载任何类(包括修复类)时,都会优先从补丁 Dex 中查找。修复类成功覆盖原类。
    • 优点:
      • 兼容性相对较好(主要依赖公开的类加载机制)。
      • 修复范围广(类级别)。
    • 缺点:
      • 性能损耗: 插桩增加了类数量和初始化开销。应用启动时插入补丁 Dex 的操作(反射、数组合并)也消耗时间。
      • CLASS_ISPREVERIFIED 问题 (Dalvik): 在 Dalvik 虚拟机(Android < 5.0)上,如果一个类在 dexopt 时被验证为只引用了同一个 Dex 内的类,会被打上 CLASS_ISPREVERIFIED 标记。插桩导致工具类引用了主 Dex 外的类(补丁 Dex 里的修复类),违反此假设,导致 pre-verify 崩溃。需要通过防止类被打上 PREVERIFIED 标记的 Hack 解决(如让所有类都引用一个独立的帮助 Dex 中的类),进一步增加复杂性。
      • Art 兼容性问题: Art 采用 AOT 编译,直接修改 dexElements 后,已 AOT 编译的代码可能不会被重新编译执行,导致修复在某些情况下不生效(尤其涉及类结构变更时)。需要结合解释执行或强制 deopt。
      • 补丁体积较大: 包含整个修改后的类文件。
    • 适用场景: 对启动时间不敏感、需要兼容较老系统(尤其是 Dalvik)的应用。目前逐渐被更优方案取代。
  2. 底层替换方案 (代表:AndFix / Sophix 底层方法替换)

    • 原理: 直接修改虚拟机层的方法结构或 Native 指针。
      • AndFix: 主要针对 Dalvik。
        • Dalvik 中,Java 方法通过 Method 结构体表示,其中包含一个指向其实现的 insns 指针(指向 DEX 字节码)和 accessFlags
        • AndFix 通过 JNI Native 代码,找到目标方法(有 Bug 的方法)和补丁方法(修复后的方法)对应的底层 Method 结构体。
        • 直接将目标方法的 insns 指针替换为补丁方法的 insns 指针。同时可能需要修改 accessFlags 等属性。
        • 后续调用该方法时,实际执行的是补丁方法的字节码。
      • Sophix (方法级): 在 AndFix 思路上做了增强和兼容性处理,尝试支持 Art。
        • Art 中方法结构更复杂(ArtMethod 对象),包含更多信息(JIT/Profiling 信息、入口点地址等)。
        • 替换 ArtMethod 的难度和风险更高。Sophix 采用了更谨慎的替换策略(如替换部分关键字段),并处理了 JIT 缓存等问题,但兼容性依然不如 Dex 替换方案完美。
    • 优点:
      • 即时生效: 无需重启应用或 Activity,修复立刻生效(对用户体验最好)。
      • 补丁体积小: 只需包含修改的方法及其直接引用类(理论上)。
      • PREVERIFIED 问题: 不依赖类加载机制。
    • 缺点:
      • 兼容性差: 严重依赖虚拟机内部实现细节(Method/ArtMethod 结构)。不同 Android 版本、不同 OEM 厂商的 ROM 差异巨大,极易导致崩溃。Android 版本升级(尤其是 Art 的演进)经常导致方案失效。Sophix 也仅在其支持的特定版本上保证方法替换。
      • 修复范围受限: 只能修改方法体内部逻辑。无法进行以下操作:
        • 增/删/改字段 (Field)
        • 增/删方法 (Method)
        • 增/删/改类 (Class) 及其继承关系、接口实现
        • 修改构造函数
        • 修改静态初始化块 (<clinit>)
      • 稳定性风险高: 直接操作运行时内存结构,风险极高。错误替换可能导致难以排查的崩溃或诡异行为。
    • 适用场景: 对即时性要求极高且修改内容严格限定为简单方法体内部逻辑变更的场景(如紧急修复一个关键计算函数)。需严格测试目标 Android 版本。不推荐作为主要热修复手段。
  3. 全量 Dex 替换方案 (代表:Tinker)

    • 原理: 比较新、旧 APK 的 Dex 文件差异(BSDiff 等算法),生成一个体积较小的差异补丁包(.patch 文件)。在客户端,将补丁包与手机上的旧 APK 的 Base Dex 进行合并,重新生成一个完整的新 Dex 文件。然后利用类加载机制(类似方案1),用这个新 Dex 完全替换旧的 Base Dex(或多个 Dex)。
    • 优点:
      • 修复能力强大: 支持增/删/改类、方法、字段、资源(需配合其资源修复模块)、So 库(需重启)。功能最接近发布新版本。
      • 兼容性极佳: 核心是加载一个完整的新 Dex,不涉及底层 Hack,对 Android 版本和 ROM 兼容性好。
      • 稳定性高: 替换的是整个 Dex 单元,避免了底层替换的风险。
      • 社区活跃,文档完善: 微信团队开源,应用广泛,社区支持好。
    • 缺点:
      • 需要重启生效: 合并生成新 Dex 的操作通常在下次启动时进行(冷启动修复)。部分场景支持“温重启”(重启部分组件,如非 ApplicationContentProvider)。
      • 补丁体积相对较大: 虽然用了差量,但改动较多时补丁仍可能较大(尤其涉及资源或大型 So 库时)。比底层替换方案大,但比插桩方案只包含修改类的方式通常要小(因为插桩方案包含整个修改类,Tinker 的差量更细)。
      • 性能开销 (合并过程): 在低端设备上,合并 Dex 文件的操作可能比较耗时,影响启动速度(但只发生在打补丁后的第一次启动)。
      • 磁盘空间占用: 需要在设备上存储 Base APK 和合并后的新 Dex 文件。
    • 适用场景: 目前最主流、最推荐的方案。适用于绝大多数需要热修复的场景,特别是修复范围较大、涉及结构变更、对稳定性要求高的应用。
  4. 混合方案 / 综合方案 (代表:阿里 Sophix - 非底层方法替换部分)

    • 原理: 并非单一技术,而是根据修复内容的类型(类、资源、So)和修复生效时间要求(即时、重启),智能选择最合适的技术组合
      • 类修复: 优先采用类似全量 Dex 替换的思路(可能优化了差量和加载过程),保证强大的修复能力和兼容性。放弃了高风险的即时底层方法替换作为主要手段(仅可能作为可选项或辅助)。
      • 资源修复: 采用成熟的 AssetManager 重建方案。Sophix 声称解决了不同 Android 版本(特别是 O 及以上)的资源修复兼容性问题,可能通过更精细的资源表 (resources.arsc) 合并或重建策略。
      • So 修复: 采用稳妥的重启后加载补丁路径 So 的方案。
      • 核心思想: 通过强大的后端服务和客户端 SDK,在生成补丁阶段就分析出最优的修复策略和最小补丁包;在客户端应用阶段根据设备环境选择最安全可靠的加载方式。
    • 优点:
      • 功能全面: 一站式解决类、资源、So 修复。
      • 兼容性优秀: 规避了高风险技术,重点保证各模块在主流系统上的兼容性。
      • 补丁生成优化: 可能结合多种差量算法和策略,生成更小的补丁包。
      • 部署灵活: 云端管控能力强。
    • 缺点:
      • 商业化方案: Sophix 是阿里云的商业化产品(有免费额度),非完全开源(核心代码闭源)。
      • 需要重启 (大部分情况): 类修复和 So 修复通常仍需重启生效(类修复可能是轻量级重启)。
      • 集成依赖: 需要依赖 Sophix SDK 及其后端服务。
    • 适用场景: 追求开箱即用、一站式解决方案、有商业化预算支持、对阿里云服务接受度高的团队。特别适合大型复杂应用。
  5. Instant Run (Google 官方 / AS 内置)

    • 原理: 严格来说,Instant Run 是开发调试工具,并非面向生产环境的热修复方案。但其部分技术(尤其是增量构建和热/温交换)启发了热修复。
      • 热交换 (Hot Swap): 仅修改方法体内部逻辑 - 类似底层替换(但更安全,可能利用了 ART 的 Debugger 或 JVMTI 接口)。
      • 温交换 (Warm Swap): 修改资源或修改了类结构(如增删方法字段) - 需要重启 Activity。
      • 冷交换 (Cold Swap): 涉及清单文件修改、继承关系变更等 - 需要重启应用。
    • 优点: 开发调试效率极高。
    • 缺点:
      • 仅限 Debug 模式: 严重依赖 IDE 和 Debug 环境,无法用于线上发布。
      • 稳定性/兼容性: 在复杂的项目或某些设备上可能不稳定。
    • 适用场景: 仅用于开发阶段,加速编译-部署-调试循环。

三、方案选择的关键考量因素

  1. 修复范围与能力:

    • 需要修复什么?简单方法体 Bug?增删字段/方法/类?修改资源?更新 So 库?
    • Dex 替换 / 全量替换 / 混合方案 > 底层替换方案。
  2. 生效时间要求:

    • 是否需要即时生效(无感知)?是否可以接受重启应用?是否可以接受重启 Activity?
    • 底层替换 (即时) > 轻量级重启 (部分混合方案可能支持) > 重启 Activity (温重启) > 重启应用 (冷启动)。
  3. 稳定性与兼容性:

    • 对线上崩溃的容忍度?目标用户的 Android 版本和机型分布?
    • 全量替换 / Dex 替换 / 混合方案 > 底层替换方案。
  4. 补丁包大小:

    • 用户网络环境?对下载速度的要求?
    • 底层替换 (最小) > 全量替换 (差量优化后) ≈ Dex 替换 (包含修改类) > 全量替换 (无优化) / Dex 替换 (包含过多类)。
  5. 性能影响:

    • 应用启动时间敏感度?运行时性能损耗?
    • 底层替换 (运行时无感) > 全量替换 (首次合并耗时) > Dex 插桩 (类加载开销)。
  6. 接入成本与生态:

    • 团队技术栈?是否愿意/有能力维护自研方案?是否接受商业化方案?
    • 成熟开源方案 (Tinker) / 商业化方案 (Sophix) > 自研方案 (高成本,高风险)。
  7. 安全性:

    • 如何保证补丁包的来源合法性和完整性(签名验证)?如何防止补丁被篡改?
  8. 平台政策 (Google Play):

    • 特别注意: Google Play 对非 Google 自身的代码热更新(特别是修改 DEX 字节码的行为)有严格限制。使用热修复可能导致应用被下架。国内市场和独立分发渠道无此限制。

四、最佳实践建议

  1. 首选成熟开源方案 (Tinker): 对于大多数团队和应用,Tinker 是目前综合最优的选择:功能强大(类/资源/So)、兼容性好、稳定性高、社区活跃、文档齐全。其需要重启的缺点在大多数场景是可以接受的折衷。
  2. 考虑商业化方案 (Sophix): 如果追求更便捷的一站式服务(尤其资源修复兼容性声称更好)、有预算、且接受云服务依赖,Sophix 是一个省心的选择。
  3. 谨慎使用底层替换 (AndFix / Robust): 仅建议在极其紧急修复内容严格符合限制(仅方法体内部逻辑)的场景下,作为临时补救措施。务必进行充分测试。Robust 在底层替换基础上做了改进(自动生成补丁类),但本质局限仍在。
  4. 避免使用过时的插桩方案: 如无特殊兼容性要求(如必须支持极老的 Dalvik 设备),不推荐使用纯 Dex 插桩方案(Nuwa 等),因其性能和兼容性问题在现代设备上更突出。
  5. 明确区分开发与生产: 绝对不要将 Instant Run 用于线上热修复。
  6. 重视测试: 建立完善的补丁测试流程,包括单元测试、自动化 UI 测试、Monkey 测试、覆盖目标机型和系统版本的兼容性测试。热修复本身的 Bug 可能导致更严重的线上问题。
  7. 灰度发布与监控: 热修复补丁必须采用灰度发布策略。同时加强线上监控(崩溃率、ANR、关键指标),一旦发现补丁引入问题,能迅速回滚。
  8. 安全加固: 对补丁包进行签名校验,确保其完整性和来源可信。防止补丁被恶意篡改。
  9. 关注 Google Play 政策: 如果应用上架 Google Play,务必仔细阅读并遵守其关于代码更新的政策,避免违规。考虑使用 App Bundle 和 In-App Updates 等官方机制。

五、总结

Android 热修复是一个涉及虚拟机机制、类加载、资源管理、Native 层的复杂技术。没有完美的“银弹”方案,选择时需要根据应用的具体需求(修复范围、生效时间、稳定性要求、性能、成本)进行权衡。

  • 追求强大修复能力、高稳定性、良好兼容性: Tinker (全量替换) 是当前开源首选。
  • 追求便捷、一站式服务、资源修复优化: Sophix (混合方案) 是优秀的商业化选择。
  • 追求即时生效且愿意承担高风险: Robust (改进的底层替换) 可作为特定场景下的补充(但非主力)。
  • 避免使用: 过时的插桩方案、高风险的纯底层替换 (AndFix)、以及仅用于开发的 Instant Run。

无论选择哪种方案,严格的测试、灰度发布和监控都是保障线上稳定性的关键。热修复是强大的工具,但也需谨慎使用。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML前端颜色渐变动画完整指南

渐变动画已经成为现代网页设计中不可或缺的元素&#xff0c;它们不仅能为网站增添视觉吸引力&#xff0c;还能显著提升用户体验。通过巧妙运用CSS渐变动画&#xff0c;开发者可以创造出令人印象深刻的动态背景效果&#xff0c;而无需依赖图片或复杂的脚本。 渐变动画的魅力所在…

b-up:Enzo_mi:Transformer DETR系列

1.视频1&#xff1a;self-Attention&#xff5c;自注意力机制 &#xff5c;位置编码 &#xff5c; 理论 代码 注意&#xff1a; q-查询; k-商品标签&#xff1b; v-值&#xff08;具体商品&#xff09; * 不是指乘法&#xff0c;类似概念 a1:相似度&#xff1b; b1:总分 若想…

算法题(179):单调栈

审题&#xff1a; 本题是单调栈的模板题 补充&#xff1a;单调栈 单调栈中的数据始终保持单调递增或单调递减 使用情景&#xff1a;给定一个数组&#xff0c;要求寻找 1.某个数左侧&#xff0c;离他最近且值大于他的数 2.某个数左侧&#xff0c;离他最近且值小于他的数 3.某个数…

CF每日5题(1500-1600)

545C 贪心 1500 题意&#xff1a;给 n 棵树在一维数轴上的坐标 xix_ixi​ &#xff0c;以及它们的长度 hih_ihi​。现在要你砍倒这些树&#xff0c;树可以向左倒也可以向右倒&#xff0c;砍倒的树不能重合、当然也不能覆盖其他的树原来的位置&#xff0c;现在求最大可以砍倒的…

HW蓝队:天眼告警监测分析之Web攻击

Web攻击 信息泄露 敏感数据包括但不限于:口令、密钥、证书、会话标识、License、隐私数据(如短消息的内容)、授权凭据、个人数据(如姓名、住址、电话等)等&#xff0c;在程序文件、配置文件、日志文件、备份文件及数据库中都有可能包含敏感数据 信息收集方法 漏洞分类 备份文…

大腾智能国产3D CAD软件正式上架华为云云商店

深圳市大腾信息技术有限公司&#xff08;以下简称“大腾智能”&#xff09;与华为云达成深度合作&#xff0c;大腾智能CAD软件及配套服务通过了华为云在功能适配、安全可用、稳定高效等方面的严选商品认证&#xff0c;已正式上架华为云云商店&#xff0c;成为华为云云商店的联营…

论文复现-windows电脑在pycharm中运行.sh文件

1.更改终端路径&#xff08;前提&#xff1a;已下载git bash&#xff09;2.授权打开pycharm终端&#xff0c;输入 chmod x 文件名3.根据当前位置&#xff0c;运行.sh文件

开关电源安全保护电路:浪涌保护、过流保护、过压保护

开关电源安全保护电路:浪涌保护、过流保护、过压保护 引言 对于开关电源而言, 安全、可靠性历来被视为重要的性能之一. 开关电源在电气技术指标满足电子设备正常使用要求的条件下, 还要满足外界或自身电路或负载电路出现故障的情况下也能安全可靠地工作. 为此, 须有多种保护措…

C语言(十)

一、函数概述函数是面向过程编程思想的具体体现&#xff0c;主要作用&#xff1a;降低程序之间的耦合性提高代码的复用性和可维护性一个完整的 C 程序由**一个或多个程序模块&#xff08;源文件&#xff09;**组成。为便于开发与调试&#xff0c;通常会将代码拆分为多个源文件&…

QT项目-仿QQ音乐的音乐播放器(第二节)

目录 自定义控件&#xff1a; BtForm类中实现 BtForm上的动画效果 自定义控件&#xff1a; 该控件实际由&#xff1a;图⽚、⽂字、动画三部分组成。图⽚和⽂字分别⽤QLabel展⽰&#xff0c;动画部分内部实际为4 个QLabel。 ① 将BtForm的geometry的宽度和⾼度修改为200*35。…

【世纪龙科技】数字课程资源-新能源汽车概论

一、课程介绍本课程为通过项目任务式教学&#xff0c;全面系统的讲解了新能源汽车的基础知识及相关技能&#xff0c;培养和提高学生的动手能力和理论知识的工程应用能力。以典型工作任务带动知识与技能的学习&#xff0c;采用项目教学培养学生的岗位技能、学习能力和职业素养。…

iOS Core Data 本地数据库 使用详解:从模型关系到数据操作

一、引言&#xff1a;Core Data&#xff0c;在本地数据持久化中的地位在 iOS 开发中&#xff0c;本地数据存储几乎是每一个 App 都绕不开的问题。无论是缓存用户信息、离线浏览内容&#xff0c;还是记录用户操作历史&#xff0c;一个合适的数据持久化方案都能大大提升应用的体验…

Java-79 深入浅出 RPC Dubbo 动态路由架构详解:从规则设计到上线系统集成

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; AI炼丹日志-30-新发布【1T 万亿】参数量大模型&#xff01;Kim…

Linux内核中动态内存分配函数解析

在C语言中&#xff0c;动态内存分配通常用于在运行时申请内存。在内核编程中&#xff0c;动态内存分配与用户空间有所不同&#xff0c;因为内核需要更谨慎地处理内存&#xff0c;且不能使用用户空间的库&#xff08;如glibc&#xff09;。下面我们将详细分析Linux内核中动态申请…

Next.js 中配置不同页面布局方案

在 Next.js 应用中&#xff0c;你可以通过多种方式实现某些页面全屏、某些页面带菜单/页眉/页脚的需求。以下是几种实现方案&#xff1a; 方案一&#xff1a;使用多个布局组件 1. 创建不同的布局组件 // app/default-layout.tsx import Header from /components/header; import…

Spring Boot 使用外置 Servlet 容器:从配置到部署全指南

在 Spring Boot 开发中&#xff0c;我们通常使用嵌入式 Servlet 容器&#xff08;如 Tomcat&#xff09;&#xff0c;它能将应用打包成可执行 JAR&#xff0c;简化部署流程。但在某些场景下&#xff08;如需要支持 JSP、复杂的容器定制或企业级部署规范&#xff09;&#xff0c…

借助AI学习开源代码git0.7之九diff-files

借助AI学习开源代码git0.7之九diff-files diff-files.c 是一个用于比较工作目录中的文件和 Git 索引&#xff08;暂存区&#xff09;中文件的工具。 实质上&#xff0c;它是 git diff命令在不指定特定提交时功能的核心实现。 主要功能分析&#xff1a; 1. 核心功能 diff-files …

社区资源媒体管理系统设计与实现

社区资源媒体管理系统设计与实现 1. 系统概述 社区资源媒体管理系统是一个专为社区户外广告打造的高效、专业化平台&#xff0c;旨在实现社区媒体的数字化管理、智能投放和便捷交易。该系统将整合社区各类广告资源&#xff0c;为广告主、物业公司和社区居民提供一站式服务。 1.…

12.1.6 weak_ptr

weak_ptr weak_ptr会指向一个share_ptr&#xff08;使用一个share_ptr来初始化weak_ptr&#xff09;&#xff0c;但并不会增加这个share_ptr的引用计数器&#xff0c;其析构也不会减少share_ptr的引用计数器。 构造函数及使用 #include <iostream> #include <memory&g…

深度分析Java内存模型

Java 内存模型&#xff08;Java Memory Model, JMM&#xff09;是 Java 并发编程的核心基石&#xff0c;它定义了多线程环境下线程如何与主内存&#xff08;Main Memory&#xff09;以及线程的本地内存&#xff08;工作内存&#xff0c;Working Memory&#xff09;交互的规则。…