线上故障紧急处理手册:如何在不重启的情况下用jstack救活死锁应用

第一章:线上故障紧急处理手册的核心价值

在现代分布式系统架构中,线上服务的稳定性直接关系到企业声誉与用户信任。面对突发性故障,响应速度与处理效率成为关键指标,而《线上故障紧急处理手册》正是提升应急响应能力的核心工具。它不仅为运维与开发团队提供标准化的应对流程,还能显著缩短平均恢复时间(MTTR)。

快速定位问题根源

当系统出现异常时,手册中预设的诊断路径可引导工程师迅速执行关键检查。例如,通过日志聚合平台检索错误模式、验证依赖服务健康状态、检查配置变更历史等。这些步骤被固化为标准操作清单,减少人为判断误差。
  • 检查监控仪表盘中的核心指标(如CPU、内存、请求延迟)
  • 查看最近一次部署记录是否引入变更
  • 调用健康检查接口确认服务可用性

统一团队协作语言

在高压的故障处理场景下,沟通成本极易上升。手册定义了统一的术语、响应等级和职责分工,确保跨职能团队在同一框架下协同工作。例如,明确“P1级故障”触发条件及对应的通知机制。
故障等级影响范围响应时限
P0全站不可用5分钟内响应
P1核心功能失效15分钟内响应

内置自动化恢复脚本示例

# check_service_status.sh # 检查关键服务运行状态并自动重启异常进程 SERVICE_NAME="api-gateway" STATUS=$(systemctl is-active $SERVICE_NAME) if [ "$STATUS" != "active" ]; then echo "[$(date)] $SERVICE_NAME is down. Restarting..." >> /var/log/recovery.log systemctl restart $SERVICE_NAME else echo "[$(date)] $SERVICE_NAME is running." >> /var/log/healthcheck.log fi
graph TD A[告警触发] --> B{是否在手册覆盖范围内?} B -->|是| C[执行预设响应流程] B -->|否| D[记录新案例并进入知识库] C --> E[恢复服务] E --> F[事后复盘并更新手册]

第二章:jstack工具深度解析与工作原理

2.1 jstack命令语法与关键参数详解

`jstack` 是JDK自带的Java线程转储工具,用于生成虚拟机当前时刻的线程快照(thread dump),帮助分析线程阻塞、死锁等问题。
基本语法结构
jstack [option] <pid>
其中 ` ` 是目标Java进程的进程ID。该命令会输出指定JVM进程中所有线程的堆栈信息。
常用参数说明
  • -l:显示额外的锁信息,如持有的监视器和可重入锁;
  • -F:强制输出线程堆栈,当正常 `jstack` 无响应时使用;
  • -m:混合模式,同时显示Java和本地C/C++帧。
典型应用场景
在排查死锁时,推荐使用:
jstack -l <pid>
该命令能识别出是否存在“等待持有锁”的循环依赖,并明确标注java.lang.Thread.State: BLOCKED状态及锁地址,为问题定位提供直接依据。

2.2 Java线程状态模型与死锁判定标准

Java线程在其生命周期中经历六种状态,定义在`Thread.State`枚举中:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING 和 TERMINATED。这些状态反映了线程在竞争CPU资源和等待同步锁时的行为。
线程状态转换图示
NEW → RUNNABLE → RUNNING ↔ BLOCKED RUNNABLE → WAITING (via wait()/join()) RUNNABLE → TIMED_WAITING (via sleep(3000)) Any → TERMINATED (on completion)
死锁的四个必要条件
  • 互斥条件:资源不能被多个线程共享。
  • 持有并等待:线程持有至少一个资源,并等待获取其他被占用的资源。
  • 不可剥夺:已分配的资源不能被强制释放。
  • 循环等待:存在线程等待环路,如T1等T2,T2等T1。
死锁检测代码示例
// 模拟两个线程互相持有对方所需锁 Object lockA = new Object(); Object lockB = new Object(); // Thread-1 new Thread(() -> { synchronized (lockA) { System.out.println("Thread-1 locked A"); try { Thread.sleep(100); } catch (InterruptedException e) {} synchronized (lockB) { System.out.println("Thread-1 locked B"); } } }).start(); // Thread-2 new Thread(() -> { synchronized (lockB) { System.out.println("Thread-2 locked B"); synchronized (lockA) { System.out.println("Thread-2 locked A"); } } }).start();
上述代码极可能引发死锁:当Thread-1持有A等待B,而Thread-2持有B等待A时,形成循环等待,满足死锁判定标准。

2.3 jstack输出日志结构化解读实战

在排查Java应用线程阻塞或死锁问题时,`jstack`生成的线程转储日志是关键诊断依据。通过结构化解析可快速定位问题根源。
线程栈基本结构
每个线程条目包含线程名、ID、状态及调用栈。例如:
"main" #1 prio=5 os_prio=0 tid=0x00007f8c8c00a000 nid=0x1b3b runnable [0x00007f8c91d5f000] java.lang.Thread.State: RUNNABLE at java.io.FileOutputStream.writeBytes(Native Method) at java.io.FileOutputStream.write(FileOutputStream.java:326)
其中,`tid`为JVM线程ID,`nid`为本地线程ID(十六进制),`RUNNABLE`表示线程当前状态。
常见线程状态与含义
  • RUNNABLE:正在运行或就绪
  • BLOCKED:等待进入synchronized块
  • WAITING:无限期等待其他线程通知
  • TIMED_WAITING:限时等待
结合状态与堆栈能精准识别死锁、锁竞争等并发问题。

2.4 定位死锁线程的典型特征与模式识别

在多线程程序中,死锁通常表现为线程长时间停滞,无法推进执行。最常见的特征是多个线程相互持有对方所需的锁资源,形成循环等待。
典型死锁代码示例
synchronized (objA) { System.out.println("Thread 1: Locked objA"); try { Thread.sleep(100); } catch (InterruptedException e) {} synchronized (objB) { // 等待 objB System.out.println("Thread 1: Locked objB"); } }
上述代码若与另一线程以相反顺序锁定 objB 和 objA,则极易引发死锁。关键在于锁获取顺序不一致。
常见识别模式
  • 线程状态为 BLOCKED 且持续时间异常
  • 堆栈跟踪中出现嵌套 synchronized 或 lock() 调用
  • JVM dump 显示循环等待链
通过监控线程堆栈和锁依赖关系,可有效识别潜在死锁模式。

2.5 jstack与其他诊断工具的协同使用场景

在复杂生产环境中,单一工具难以全面定位问题。jstack 作为线程堆栈分析利器,常与 jstat、jmap 和 jps 等工具协同使用,实现全方位 JVM 诊断。
与 jstat 的内存与GC联动分析
通过jstat -gc观察 GC 频率与堆内存变化,若发现频繁 Full GC,再结合jstack输出线程快照,可判断是否因锁竞争导致线程阻塞,进而引发对象滞留。
jstat -gc 1234 1000 jstack 1234 > thread_dump.log
上述命令每秒输出一次 GC 状态,并保存线程堆栈。通过比对时间点,可关联 GC 尖峰与特定线程状态(如 BLOCKED)。
与 jmap 的内存泄漏联合排查
jmap -histo显示某类实例异常增多时,使用jstack检查是否有线程持续创建该对象或持有强引用无法回收。
  • jps 定位进程 ID
  • jstat 监控 GC 行为
  • jstack 分析线程阻塞
  • jmap 生成堆转储
这种分层协作机制显著提升故障定位效率。

第三章:无重启条件下排查死锁的完整流程

3.1 故障现场保护与线程快照采集时机

在系统发生异常时,及时保护故障现场是定位问题的关键前提。线程状态的瞬时性决定了快照必须在关键执行点采集,避免因延迟导致上下文丢失。
何时触发线程快照采集
理想的采集时机包括:方法入口与出口、异常抛出点、锁竞争激烈区域以及长时间阻塞操作前后。这些节点能有效反映调用链路的执行路径和资源争用情况。
// 示例:通过 JVM API 主动 dump 线程信息 ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); long[] threadIds = threadMXBean.getAllThreadIds(); for (long tid : threadIds) { ThreadInfo ti = threadMXBean.getThreadInfo(tid, 100); System.out.println(ti.getThreadName() + ": " + ti.getThreadState()); }
该代码通过 JMX 接口获取所有线程的栈轨迹与状态,适用于程序内部自动触发快照。参数 `100` 表示最多采集 100 层调用栈,便于分析深层嵌套调用。
采集策略对比
策略实时性开销适用场景
主动轮询测试环境深度监控
异常触发生产环境故障捕获

3.2 多次采样分析锁定竞争路径

在高并发系统中,仅靠单次 trace 往往无法稳定复现竞态条件。需通过多次采样聚合分析,识别高频冲突路径。

采样策略配置
  • 启用 runtime/pprof 的 mutex profile,采样间隔设为 10ms
  • 连续采集 50 次,剔除首尾 5% 异常样本
关键竞争栈提取
// 从 pprof.Profile 获取 top 3 冲突调用栈 profile := pprof.Lookup("mutex") buf := new(bytes.Buffer) profile.WriteTo(buf, 2) // depth=2 展开锁持有者与等待者

该代码强制输出两级调用栈:第1层为sync.Mutex.Lock()调用点,第2层定位到具体业务方法(如UpdateCache()),便于横向比对多批次采样中的共现模式。

冲突路径统计表
路径ID出现频次平均阻塞时长(ms)
P-7824218.6
P-9153723.1

3.3 基于业务上下文还原死锁成因链

在高并发系统中,数据库死锁往往并非孤立事件,而是多个业务操作在特定时序下的连锁反应。通过结合应用日志、事务追踪与执行计划,可构建完整的死锁成因链。
事务执行时序分析
利用分布式追踪系统(如OpenTelemetry)采集各服务节点的调用链,定位持有锁资源的事务起点与终点。关键字段包括:事务ID、SQL语句、加锁类型、等待对象。
典型场景复现
-- 事务A BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; -- 持有行锁 UPDATE accounts SET balance = balance + 100 WHERE id = 2; -- 等待事务B释放 COMMIT; -- 事务B BEGIN; UPDATE accounts SET balance = balance - 50 WHERE id = 2; -- 持有行锁 UPDATE accounts SET balance = balance + 50 WHERE id = 1; -- 等待事务A释放 COMMIT;
上述代码模拟了典型的交叉更新导致死锁。事务A与B分别持有一部分资源并请求对方已锁定的资源,形成循环等待。
成因链建模
步骤事务操作持有锁等待锁
1A更新id=1row_lock(1)-
2B更新id=2row_lock(2)-
3A更新id=2row_lock(1)row_lock(2)
4B更新id=1row_lock(2)row_lock(1)

第四章:真实生产环境下的jstack应急实践

4.1 模拟Web应用因锁顺序错乱导致死锁

在高并发Web应用中,多个线程对共享资源的访问若未遵循一致的加锁顺序,极易引发死锁。考虑两个服务同时操作两个账户进行资金转账的场景。
模拟死锁代码
var accountA, accountB sync.Mutex func transferAtoB() { accountA.Lock() time.Sleep(100 * time.Millisecond) // 模拟处理延迟 accountB.Lock() // 转账逻辑 accountB.Unlock() accountA.Unlock() } func transferBtoA() { accountB.Lock() // 锁顺序与前者相反 accountA.Lock() // 转账逻辑 accountA.Unlock() accountB.Unlock() }
上述代码中,transferAtoB先锁 A 后锁 B,而transferBtoA顺序相反。当两个 goroutine 分别执行这两个函数时,可能互相持有对方所需的锁,形成循环等待。
预防策略
  • 统一全局锁顺序,如按对象地址或ID排序后依次加锁
  • 使用超时机制(TryLock)避免无限等待
  • 引入死锁检测工具进行静态分析

4.2 使用jstack定位synchronized嵌套陷阱

理解synchronized嵌套死锁场景
当多个线程在持有锁的情况下尝试获取已被其他线程持有的锁时,可能引发死锁。尤其在嵌套使用synchronized块时,若未注意锁的顺序或作用域,极易触发该问题。
synchronized (obj1) { System.out.println("Thread 1: Holding obj1..."); try { Thread.sleep(100); } catch (InterruptedException e) {} synchronized (obj2) { // 等待 obj2 System.out.println("Thread 1: Waiting for obj2..."); } }
上述代码若与另一线程以相反顺序锁定 obj2 和 obj1,将导致相互等待。
jstack诊断线程阻塞
通过jstack <pid>可输出JVM线程快照,识别处于BLOCKED状态的线程及其锁信息。例如:
  • 查找“java.lang.Thread.State: BLOCKED”条目
  • 分析“waiting to lock monitor”和“locked by”线索
  • 定位具体代码行号及同步对象
结合线程堆栈与源码,可精准识别嵌套锁的循环等待路径,进而重构加锁逻辑,避免死锁。

4.3 分析ThreadPool中任务阻塞引发的假死现象

在高并发场景下,线程池中的任务若发生长时间阻塞,可能导致核心线程资源耗尽,进而使后续任务无法被调度,表现为系统“假死”。这种现象常出现在数据库连接超时、同步IO等待或锁竞争激烈等场景。
常见阻塞源分析
  • 网络请求未设置超时时间
  • 同步调用外部服务且响应延迟高
  • 共享资源竞争导致线程长时间等待
代码示例:模拟阻塞任务
ExecutorService pool = Executors.newFixedThreadPool(5); for (int i = 0; i < 100; i++) { pool.submit(() -> { try { Thread.sleep(60000); // 模拟阻塞 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); }
上述代码创建了固定大小为5的线程池,提交100个休眠60秒的任务。前5个任务将占用所有线程,其余任务进入队列等待。若队列容量有限,则后续任务可能被拒绝,造成请求堆积。
解决方案对比
策略说明
设置任务超时使用 Future.get(timeout, unit) 控制执行时间
异步非阻塞采用 CompletableFuture 或响应式编程模型

4.4 输出诊断报告并指导热修复代码调整

在完成运行时数据采集与异常定位后,系统自动生成结构化诊断报告,为热修复提供精准依据。
诊断报告核心字段
  • 异常类型:明确错误类别,如空指针、数组越界等;
  • 调用栈快照:记录异常发生时的完整执行路径;
  • 变量状态镜像:捕获局部变量与对象属性值;
  • 建议修复策略:基于模式匹配推荐补丁方案。
热修复代码生成示例
// 原始方法存在空指针风险 public String processUser(User user) { return user.getName().toLowerCase(); // 可能抛出NullPointerException } // 诊断系统建议的热修复版本 @Hotfix(replace = "processUser") public String processUserSafe(User user) { if (user == null || user.getName() == null) { return "unknown"; } return user.getName().toLowerCase(); }
该补丁通过增加判空逻辑消除异常风险,注解标识用于运行时方法替换。JVM通过字节码增强技术动态加载新实现,无需重启服务。
修复验证流程
采集异常 → 生成诊断报告 → 推荐补丁 → 安全审查 → 热部署 → 监控反馈

第五章:从救火到防控——构建高可用线程安全体系

在高并发系统中,线程安全问题常常成为系统崩溃的根源。传统“发现问题—紧急修复”的救火模式已无法满足现代应用对稳定性的要求,必须转向主动防控。
识别共享资源竞争
多个线程访问共享变量时极易引发数据不一致。例如,在订单服务中,库存计数器若未加保护,可能导致超卖:
private static int stock = 100; public synchronized boolean deductStock() { if (stock > 0) { stock--; // 非原子操作 return true; } return false; }
使用synchronizedReentrantLock可保证方法级别的互斥访问。
采用无锁编程策略
对于高频读写场景,锁机制可能成为性能瓶颈。利用AtomicInteger等原子类可实现高效无锁更新:
private static AtomicInteger stock = new AtomicInteger(100); public boolean deductStock() { return stock.updateAndGet(s -> s > 0 ? s - 1 : s) > 0; }
引入线程安全设计模式
  • 不可变对象(Immutable Object)避免状态修改
  • ThreadLocal 存储线程私有数据,隔离共享风险
  • 使用 ConcurrentHashMap 替代 synchronized Map 提升并发性能
构建运行时监控能力
通过 JVM 工具如 JMC 或 Arthas 实时观测线程堆栈,定位死锁与阻塞点。同时,结合日志埋点记录关键资源访问轨迹。
问题类型检测手段解决方案
竞态条件代码审查 + 压测复现加锁或原子类
死锁jstack 分析统一锁顺序

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

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

相关文章

2025年末河北粘钉一体机厂家大揭秘,口碑王者花落谁家?目前粘钉一体机找哪家关键技术和产品信息全方位测评

在包装行业智能化、高效化转型的浪潮下,粘钉一体机作为纸箱印后加工的关键设备,其市场需求持续攀升。河北,尤其是东光地区,依托深厚的产业基础,已成为国内重要的粘钉一体机生产集群。然而,面对市场上品牌林立、技…

2026年河南精铸工匠不锈钢有限公司联系电话推荐:精选推荐与使用指南

在商业合作与项目推进中,准确、高效地联系到目标企业是成功的第一步。对于需要高品质不锈钢标识产品与一体化装饰工程解决方案的客户而言,找到可靠的服务提供商至关重要。河南精铸工匠不锈钢有限公司作为业内知名的服…

好写作AI:从“搬砖思维”到“建筑师思维”,AI如何重构你的学术大脑?

还在用“挤牙膏”式写论文&#xff1f;先凑字数&#xff0c;再调格式&#xff0c;最后硬拗创新点——这套“学术流水线”思维该升级了&#xff01;人工智能时代&#xff0c;好写作AI正在悄悄重塑我们的写作思维模式&#xff1a;从“我该怎么写完”&#xff0c;变成“我该怎么想…

Open-AutoGLM入门必看:手机AI Agent三大核心组件解析

Open-AutoGLM入门必看&#xff1a;手机AI Agent三大核心组件解析 Open-AutoGLM – 智谱开源的手机端AI Agent框架。它基于视觉语言模型与自动化控制技术&#xff0c;让普通用户也能轻松实现“动口不动手”的智能操作体验。无论是日常使用还是开发调试&#xff0c;这一框架都展…

2026年银源电力联系电话推荐:精选推荐与使用指南

在当今注重安全、节能与可持续发展的能源行业背景下,无论是寻求项目合作、工程承包,还是有意加盟一家实力雄厚的电力企业,获取准确、可靠的联系方式都是至关重要的第一步。四川银源电力有限责任公司作为一家在电力行…

揭秘CMake引入第三方库的5大陷阱:90%开发者都会踩的坑,你中招了吗?

第一章&#xff1a;揭秘CMake引入第三方库的核心挑战 在现代C项目开发中&#xff0c;CMake已成为事实上的构建系统标准。然而&#xff0c;当项目需要集成第三方库时&#xff0c;开发者常面临路径管理混乱、依赖版本冲突、跨平台兼容性差等问题。这些问题不仅影响构建效率&#…

深聊东辉实业的创新成果多吗,研发成果大盘点

在特种胶粘材料领域,企业的技术实力、创新成果与服务态度是决定其市场竞争力的核心要素。面对市场上众多胶粘材料厂商,企业在选择合作伙伴时,往往会陷入如何判断厂商技术是否过硬产品创新能否匹配场景需求定制服务是…

如何快速上手YOLO11?保姆级教程带你30分钟完成部署

如何快速上手YOLO11&#xff1f;保姆级教程带你30分钟完成部署 你是不是也听说过 YOLO11&#xff0c;但一直不知道从哪开始&#xff1f;想试试最新的目标检测模型&#xff0c;却被复杂的环境配置劝退&#xff1f;别担心&#xff0c;这篇文章就是为你准备的。我们跳过繁琐的依赖…

【高并发场景必备】:Stream filter多条件性能优化的4个关键点

第一章&#xff1a;Stream filter多条件性能问题的背景与挑战 在现代Java应用开发中&#xff0c;Stream API因其声明式语法和链式操作被广泛用于集合数据的处理。然而&#xff0c;当使用filter操作进行多条件筛选时&#xff0c;尤其是在大数据集或高并发场景下&#xff0c;性能…

泛型方法为何不能重载?从字节码层面揭开擦除机制的神秘面纱

第一章&#xff1a;泛型方法为何不能重载&#xff1f;从字节码层面揭开擦除机制的神秘面纱 Java 的泛型是**伪泛型**——编译期即被类型擦除&#xff0c;运行时无泛型信息。这直接导致泛型方法无法按类型参数进行重载&#xff0c;因为擦除后方法签名完全相同&#xff0c;违反 J…

2026年汽车托运公司推荐:基于多场景实测评价,针对车辆损伤与隐性收费痛点精准指南

摘要 在汽车消费市场持续繁荣与人口跨区域流动日益频繁的背景下,私家车异地托运已成为一项普遍且刚性的需求。无论是个人车主因工作调动、长途自驾游,还是汽车经销商、二手车商、主机厂的商品车流转,都面临着将爱车…

Paraformer-large语音摘要生成:结合大模型二次处理

Paraformer-large语音摘要生成&#xff1a;结合大模型二次处理 1. 离线语音识别与智能摘要的完整链路 你有没有遇到过这种情况&#xff1a;会议录音长达两小时&#xff0c;逐字转写出来上万字&#xff0c;但真正重要的内容可能就几段&#xff1f;光有语音转文字还不够&#x…

东辉实业基本信息有哪些,一文带你全了解

问题1:东辉实业的基本信息是什么?它是一家怎样的企业? 苍南县东辉实业有限公司是一家深耕特种海绵胶带领域的专业制造厂商,2006年正式成立,注册资本1580万元,坐落于浙江温州苍南县金乡镇凉亭村,拥有2万多平方米…

线上系统突然无响应?,用jstack快速诊断线程死锁的4个关键步骤

第一章&#xff1a;线上系统突然无响应&#xff1f;jstack诊断死锁的必要性当生产环境中的Java应用突然停止响应&#xff0c;用户请求超时&#xff0c;而CPU和内存监控却未见明显异常时&#xff0c;问题很可能源于线程死锁。死锁会导致关键业务线程相互等待&#xff0c;系统无法…

福州研究生留学机构口碑排名出炉!这些稳定可靠机构,你不可错过

福州研究生留学机构口碑排名出炉!这些稳定可靠机构,你不可错过作为。从业八年的国际教育规划师,我注意到,近期许多福州地区的高校学子在规划海外深造时,普遍存在一个核心疑问:“在福州,如何找到一家稳定可靠的研…

2026年国内评价好的石笼网生产厂家口碑推荐,柔韧抗压石笼网/双隔板石笼网/六角石笼网,石笼网源头厂家怎么选择

近年来,随着国家基建工程规模持续扩大,石笼网作为河道治理、边坡防护、生态修复等领域的核心材料,市场需求呈现爆发式增长。然而,行业准入门槛低、技术同质化严重等问题,导致市场产品质量参差不齐,采购方在选择供…

开源项目二次开发:FSMN VAD WebUI定制指南

开源项目二次开发&#xff1a;FSMN VAD WebUI定制指南 1. 项目背景与核心价值 你可能已经听说过阿里达摩院开源的 FSMN VAD 模型——一个轻量高效、精度出色的语音活动检测工具。它能精准识别音频中的“哪里有人在说话”&#xff0c;广泛应用于会议转录、电话质检、语音预处理…

Qwen3-0.6B能否用于教学?高校AI课程实践案例分享

Qwen3-0.6B能否用于教学&#xff1f;高校AI课程实践案例分享 在人工智能教育快速普及的今天&#xff0c;高校教师面临一个现实问题&#xff1a;如何在有限算力条件下&#xff0c;为学生提供真实的大模型交互体验&#xff1f;Qwen3-0.6B的出现&#xff0c;为这一难题提供了极具…

YOLOv9-s.pt权重使用教程:预下载模型直接调用方法

YOLOv9-s.pt权重使用教程&#xff1a;预下载模型直接调用方法 你是不是也遇到过这种情况&#xff1a;刚想用YOLOv9跑个目标检测&#xff0c;结果第一步下载权重就卡住了&#xff1f;网速慢、链接失效、路径不对……一堆问题接踵而来。别急&#xff0c;这篇教程就是为你准备的。…

Java泛型擦除全解析,资深架构师20年经验总结(必收藏)

第一章&#xff1a;Java泛型擦除是什么意思 Java泛型擦除&#xff08;Type Erasure&#xff09;是Java编译器在编译泛型代码时所采用的一种机制&#xff0c;其核心思想是在编译期间移除泛型类型参数的信息&#xff0c;将泛型类型还原为原始类型&#xff08;Raw Type&#xff09…