Java线上OOM排查实战:从堆转储到GC Roots的根因定位
做了几年Java后端最让人心头一紧的告警不是CPU彪了不是RT降不下来而是监控屏幕上突然弹出一行红字OutOfMemoryError。OOM这四个字母一出现意味着某个JVM进程已经处于极度缺内存的状态接下来大概率是GC疯狂抖动、接口大面积超时、线程堆满甚至整个服务被系统直接杀掉。最近有个朋友去面猿辅导后端二面被问到“线上出现的OOM是如何排查的”他回来跟我复盘的时候说自己当时只答出了“用jmap dump、用MAT分析”几个关键词结果被面试官追着一路问到底层逻辑最后败下阵来。我听完最大的感受是OOM排查不是一个命令题而是一条完整的链路推理题。你不仅要能说出工具更要说清楚“为什么是这一步”“为什么这个对象会堆积”“这个内存模型下到底哪里先扛不住”。这篇文章我就按照一次真实的线上OOM排查经历来写从告警出现、现场留存到堆转储分析、根因定位再到修复和预防把整条链路摊开讲。内容会包含大量实操命令、参数解释、工具选型逻辑和踩坑记录也适合准备后端面试的同学用来梳理自己的表达结构。1. 线上OOM先分清是哪一种“内存不够了”1.1 Java堆内存不足最常见的OOM主战场绝大多数线上服务的OOM都是java.lang.OutOfMemoryError: Java heap space。堆内存是Java对象的主要存放区域平时我们new出来的对象都住在这里它又细分为新生代和老年代。新生代负责存放短命对象老年代负责存放熬过了多次GC的“老不死”对象。当堆内存不足时通常有两种情况内存溢出某一瞬间内存需求峰值超过了堆上限。比如一个接口一次性加载了百万级数据到List里再叠加并发请求堆一下子就被打满。这种场景下对象本身生命周期很短不属于泄漏属于“瞬时流量大对象”的组合问题。内存泄漏对象用完了之后因为某处错误引用导致GC无法回收堆积在堆里。这种问题很隐蔽通常表现为“内存水位持续缓慢上升隔几天或者几周后OOM”。区分这两者最关键的动作是看趋势如果OOM之前内存曲线是一个持续上扬的坡大概率是泄漏如果曲线长期平稳突然某个时间点直线冲顶大概率是瞬时峰值导致的溢出。排查的方向完全不同前者要查引用链后者要查接口流量和数据量。1.2 Metaspace溢出、直接内存溢出、线程栈溢出除了Java堆还有几类OOM容易被忽视它们报出的错误信息不一样排查手段也完全不同。java.lang.OutOfMemoryError: Metaspace元空间存的是类的元数据、方法信息、常量池等。当应用使用CGLIB、动态代理、反射生成大量新类时Metaspace会持续膨胀。我之前遇到过某个服务每处理一个请求就通过反射创建新的代理类结果运行两周后Metaspace被打爆。这类问题用jmap抓堆Dump效果有限因为Metaspace不在堆内需要用jcmd查看类加载统计或者更换更合适的诊断思路。java.lang.OutOfMemoryError: Direct buffer memory直接内存使用DirectByteBuffer进行堆外分配常见于Netty、Kafka客户端这类高性能IO组件。如果堆外内存配置不当或者ByteBuffer分配后没有释放就会报这个错。这类问题需要结合-XX:MaxDirectMemorySize参数和IO框架的使用情况来分析。java.lang.OutOfMemoryError: unable to create new native thread这个更特殊本质不是内存不够而是操作系统无法再为新的线程分配资源。常见原因有线程数无节制增加、每个线程默认栈大小过大、或者进程被系统线程数限制卡住。排查手段更偏向于查线程数量和系统ulimit而不是看堆。1.3 先搞清楚“泄漏”和“溢出”再动手很多人在排查刚开始就急着下结论这是最致命的。我建议动手之前先画一个简化的判定思路看监控曲线内存直线上升还是阶梯式上升OOM发生前是否有突发流量。看业务日志OOM发生前有没有批量导出、超大查询、循环调用等操作。看GC日志是不是老年代一直缓慢增长、Full GC越来越频繁。这三种信号组合起来基本能判断方向。泄漏类问题一定要靠“引用链分析”找到谁在持有对象溢出类问题则要回到“数据量与内存模型”的匹配度上来。2. 排查前的几个关键动作先把“现场”冻结下来2.1 第一时间用jmap保留Heap Dump线上OOM最怕的是没有“案发现场”。如果进程还在第一时间应该考虑把堆快照抓下来否则等你一顿操作完之后对象可能已经被GC清掉了排查就无从谈起。最常用的命令是jmap -dump:live,formatb,file/home/logs/heap-$(date %Y%m%d-%H%M%S).hprof pid这里我解释一下参数逻辑。formatb表示输出二进制格式这是MAT、JProfile等分析工具能识别的标准格式。live表示只保留堆中存活对象这样生成的Dump文件体积会小很多但代价是触发一次Full GC生产环境可能造成短暂的停顿。如果服务已经处于半死不活状态这反而是一种“止损式”操作如果服务还能稳定扛住考虑先用jmap -histo pid看一眼对象分布再做决定。至于为什么一定是jmap而不是别的工具因为它是JDK自带的不依赖外部环境关键是它能拿到当前JVM进程最准确的堆快照。抓Dump文件之前确认磁盘空间足够很多线上故障是Dump写到一半磁盘满了雪上加霜。2.2 提前开好自动Dump参数一次配置后面全靠它我强烈建议所有Java服务在启动参数里加上这组配置-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/home/logs/dump/ -XX:PrintGCDetails -XX:PrintGCDateStamps -Xloggc:/home/logs/gc.logHeapDumpOnOutOfMemoryError的作用是当JVM抛出OOM时自动生成堆转储文件配合HeapDumpPath指定目录。它不占用正常运行的性能却能在OOM瞬间精准抓到现场比事后手动jmap可靠得多。还要加GC日志。很多人只关注业务日志忽略GC日志的价值。GC日志记录了每一次Young GC和Full GC的时间、停顿时长、各区域内存变化在OOM排查里它是判断“内存上涨路径”的核心证据。举个例子如果GC日志显示老年代占用每半小时跳一个台阶说明有对象在持续进入老年代如果出现连续的Full GC但回收效果很差基本可以认定存在泄漏。2.3 收集日志GC日志、错误日志、业务日志一个都不能少OOM排查是典型的“多源数据交叉验证”过程。除了GC日志和Heap Dump业务日志同样重要。你需要确认OOM发生前最后几十条业务日志是什么对应哪个接口、哪个线程。有没有异常堆栈指向某个具体的类和方法。请求量、响应时间、线程池活跃数在那一刻是什么状态。这里的逻辑是Heap Dump只能告诉你对象“长什么样子”但很难告诉你对象“为什么会长成这样”。业务日志负责还原时间线和业务行为两者结合才能定位到代码层面。经验之谈保存日志的时间范围至少要在OOM发生前两三个小时太短的窗口经常不够用。3. 用MAT解剖堆转储从直方图到GC Roots3.1 先看Leak Suspects和Dominator Tree拿到Heap Dump之后我最常用的工具是Eclipse MAT。虽然它的界面不怎么好看但分析能力确实扎实。打开Dump文件后第一步不是瞎翻对象列表而是先看Leak Suspects Report这相当于工具帮你做了第一轮嫌疑犯筛查。它会把可能的泄漏点用“嫌疑对象”的形式列出来并且从GC Roots出发给出引用链。这个视图唯一的缺点是不够精确经常把一些本来就该大的对象当成嫌疑犯所以它只是起点。第二步看Dominator Tree支配树。这个视图的价值在于按“保留堆”Retained Heap排序告诉你某个对象实际“拖累”了多少内存。注意区分两个概念Shallow Heap浅堆对象本身占用的内存不包括它引用的对象。Retained Heap保留堆如果把这个对象回收掉能释放多少内存包含它间接持有的所有子对象。在OOM排查中Retained Heap才是真正有意义的指标。那些Retained Heap占比极大的对象就是内存的主要消耗者。3.2 如何从“对象太大”定位到“代码哪里错了”MAT只能给你对象结构的结论给你“哪些类产生了大量实例”的清单但根因还是得靠代码。我的做法通常是在Dominator Tree里找到Retained Heap最大的对象右键选择Path to GC Roots中的exclude weak references。查看这条引用链上有哪些业务类特别关注静态变量、ThreadLocal、缓存容器这一类“容易活得很久”的持有者。沿着引用链回到业务代码看看这些对象是怎么被创建和放进去的。举个例子如果引用链是ConcurrentHashMap - Node[] - UserInfoPurchaseRecord而持有者是某个静态缓存基本就能锁定是缓存未清理导致的对象堆积。如果引用链最终指向某个Thread那要怀疑ThreadLocal使用不当因为线程池里的线程不会销毁ThreadLocal里的数据会跟着线程一直存活。3.3 常见误判大对象本身没错错在生命周期管理分析时很容易走进一个误区看到一个巨大的byte[]就认为是问题。byte[]大不可怕可怕的是它的生命周期过长。比如一个byte[]是某个大文件的缓存内容它本身就该被频繁替换但如果这个byte[]一直被某个全局静态Map持有即使不需要了也不释放那就是典型的泄漏。另一个容易忽视的点是ArrayList和HashMap的内部数组扩容。有些对象元素不多但底层数组被扩大过Shallow Heap很大却只装了几个元素。这种情况下要检查集合初始容量是否设置合理避免反复扩容浪费内存。MAT加载几个GB的Dump文件时经常报内存不足记得调整MAT的启动参数。在MemoryAnalyzer.ini里把-Xmx调大我一般直接设成物理内存的一半以上比如机器16GB就设-Xmx8192m。这不是什么高深技巧但能省很多烦躁的时间。4. 一次三大典型案例复盘4.1 案例一缓存容器积累导致的对象持续堆积有一次我负责的详情服务在运行一个月后出现OOM监控曲线非常典型内存每天涨一点每周跳一个平台整体呈锯齿状向上攀升。用jmap抓Dump后MAT的Histogram显示大量PurchaseReportDTO实例存在Dominator Tree里定位到一个巨大的ConcurrentHashMap。顺着Path to GC Roots看下去引用链路是一个静态缓存对象持有MapMap的key是客户ID_日期value是一个ListPurchaseReportDTO。代码逻辑是每天按客户维度汇总前一天的报表数据放入缓存但只put不清理日积月累就堆满了。这种属于典型的内存泄漏修复方案我选了Caffeine替换手写Map配置了expireAfterWrite和maximumSize让缓存具备自动过期和容量上限。线上验证一周后内存曲线彻底平稳Full GC频率也大幅下降。4.2 案例二瞬时流量引发的大对象高峰这起OOM发生在一次活动中。某个接口负责查询用户三个月内全部订单并组装成大列表返回前端平时调用量不大数据量也就几千条。但在活动期间QPS突增每个请求都会在堆内创建大量订单DTO多个请求并发叠加老年代被瞬间打满紧接着报Java heap space。明显不是泄漏因为内存曲线在OOM前非常平稳是突然冲顶的。jstat看到Old区快速上涨Young GC后对象存活率异常大量对象直接进入老年代。这个案例的修复思路不是改缓存而是从三个角度控制数据的瞬态峰值接口改成按页分批查询限制单次返回条数服务入口加令牌桶限流保护内存不受瞬时流量冲击调整了新生代比例让短命大对象更容易在Young区被回收掉。经过这轮调整之后血压曲线总算平稳了。4.3 案例三动态代理把Metaspace塞满了还有一个印象深刻的案例服务跑了一周开始稳定报java.lang.OutOfMemoryError: Metaspace。这类问题用堆Dump解决不了因为Metaspace不属于Java堆。我当时用的是jcmd GC.class_stats需要配合-XX:UnlockDiagnosticVMOptions来看类加载情况结果发现某个代理类被生成了几十万个。根因是代码里有一个框架的扩展点在请求处理路径上动态生成CGLIB代理类高并发场景下每个请求都会生成一个新类导致Metaspace暴涨。修复方式是把代理生成逻辑改到启动阶段复用单一代理实例同时给JVM设置了-XX:MaxMetaspaceSize作为熔断保护。这个案例也让我反思遇到OOM先看错误信息是heap space还是Metaspace这会直接决定你要不要抓Heap Dump。5. 二面怎么答OOM排查的表达框架5.1 回答OOM排查题的“四段式”结构如果面试官问“线上出现的OOM是如何排查的”别一上来就背命令。面试官想看到的是你的系统性思维。我推荐的表达结构是这样的第一段确认OOM类型。先说根据报错信息判断是Java heap space、Metaspace还是其他类型不同OOM类型对应不同排查链路。第二段保留现场。说清楚两个动作优先看有无HeapDumpOnOutOfMemoryError自动转储如果没有且进程还在用jmap手动抓Dump。第三段分析Dump。用MAT看Leak Suspects和Dominator Tree结合Histogram找出Retained Heap最大的对象再沿着GC Roots引用链定位到业务代码。第四段根因分类与解决。区分是内存泄漏还是内存溢出泄漏给清理方案溢出给限流、分页、内存参数调整等方案。这个结构本身就是一套“自圆其说”的逻辑面试官追问任何一步你都有上下文可以支撑。5.2 面试官会追问的3个高频深水区问题第一怎么判断是内存泄漏还是内存溢出。回答思路是要看内存趋势持续增长是泄漏突发冲顶是溢出。更准确的验证方式是分析Dump中的GC Roots引用链泄漏类对象一般会被非堆内存的容器或长生命周期线程持有溢出类对象往往引用链很短最后都指向某个即将消亡的局部变量。第二如果Dump文件巨大加载不出来怎么办。这个问题考的是应急能力。可以先从GC日志反向推断也可以通过jmap -histo:live获取粗略的类实例统计。MAT加载不了就调整-Xmx或者用命令行工具jhat做简易分析但体验很差只适合临时过渡。第三线上不能随便jmap怎么办。现实中的确存在这种情况尤其是有严格变更管控的核心交易链路。可以先通过监控平台观察内存曲线和GC频率再用Arthas这类在线诊断工具做轻量分析比如用vmtool查询实例数量和分布。必要的时候走审批流程在低峰期做一次受控的Dump抓取。6. 常见问题速查与避坑经验6.1 线上OOM排查FAQ速查表症状可能的根因优先排查动作内存曲线持续缓慢上涨数天后OOM缓存未清理、ThreadLocal持有、连接池泄漏抓Heap Dump看Retained Heap和GC Roots引用链内存突然冲顶接口超时马上OOM瞬时大对象、高并发请求峰值查接口QPS和单次请求的内存占用考虑限流和分页报Metaspace错误动态代理类过多、框架生成类泄漏用jcmd看类数量核查代理生成逻辑报Direct buffer memoryNetty或IO组件堆外内存分配过多核查直接内存配置检查ByteBuffer是否释放报unable to create new native thread线程数过多超出系统限制查线程dump确认是否线程泄漏或者栈大小过大这五种症状是线上最常碰到的遇到OOM先对照这个表格框定范围能省掉大量瞎猜时间。还有一个在线下很容易踩的坑抓Dump用了jmap -dump:live以为万事大吉结果触发了一次Full GC把还在执行中的大对象全部回收了Dump里什么都看不到。所以在服务还能扛的情况下手动抓堆快照尽量不带live让完整堆状态落盘分析完再考虑GC的影响。6.2 一些实操中的独家体会OOM排查做了几次之后我的一个深体会是线上故障的根因往往不在故障发生的瞬间。它可能藏在三周前的一次发版藏在一个看似无害的静态变量藏在一个没有设置过期时间的缓存里。排查的价值在于把“内存为什么不够”翻译成“代码里到底谁在一直占用”而不是靠重启解决一时的问题重启之后故障还会回来。另一个建议是排查OOM的时候一定要设计“验证环节”。修复代码之后不能只观察一两天就宣布解决。比如缓存泄漏的问题至少连续观察一个完整业务周期确认内存水位没有继续上涨瞬时流量造成的溢出则要等到下一次类似活动再做一次压测验证。没有验证的修复只是猜测验证过的修复才算是真闭环。最后分享一个小心得我每次排查完OOM都会把Dump文件、GC日志、分析截图、根因结论整理成一份简短的复盘文档放进团队的故障知识库里。下次再遇到相似的OOM直接按旧方案走一遍效率会非常高。线上OOM虽然吓人但本质上是有迹可循的只要思路清晰、步骤完整、工具趁手它就会从“事故”变成一次很好的系统体检。

相关新闻

Web开发、安全与嵌入式实战:一张热词表拆解三大战场

Web开发、安全与嵌入式实战:一张热词表拆解三大战场

我平时用“web”当搜索词的时候,经常会把一大批奇奇怪怪的零散需求搜到一起。比如有一天我想查“web页面pdf打印”,结果后面的关联词里跟着“esp32内嵌web网页”“海康威视视频web插件”“b站首页web推荐算法”“acunetix web漏洞扫描器”,还…

2026/10/5 4:26:31 阅读更多 →
基于SpringBoot的高校学生公寓智能分配平台设计与实现

基于SpringBoot的高校学生公寓智能分配平台设计与实现

每年九月的开学季,最让宿管科头疼的往往不是床位不够,而是“怎么把几千个新生快速、合理地塞进不同的房间”。表格导来导去、辅导员来回商量、学生群里的作息冲突投诉接二连三——宿舍分配管理这件事,看起来只是排个床位,实际上牵…

2026/10/5 4:26:31 阅读更多 →
Colmap中PatchMatch源码实战:从编译报错到深度图调优

Colmap中PatchMatch源码实战:从编译报错到深度图调优

1. 这不是“看懂就行”的源码阅读,而是要让PatchMatch在Colmap里真正跑起来如果你搜“Colmap中 patchmatch源码”,大概率正卡在某个具体环节:编译报错说找不到patch_match_stereo.h、调试时发现PatchMatch::ComputeCostVolume函数里cost volu…

2026/10/5 4:25:30 阅读更多 →

最新新闻

WorkBuddy实战:智能家居竞品调研从三天压缩到三小时

WorkBuddy实战:智能家居竞品调研从三天压缩到三小时

前两天临时接到一个任务,要在三天内给领导交一份智能家居行业的竞品调研报告。换作以前,这种活意味着我要在十几个网站之间来回切换,翻官网、查财报、扒第三方数据,光收集资料就能耗掉一整天,更不用说整理成结构清晰的…

2026/10/5 5:01:44 阅读更多 →
HDFS读写原理与Java API实战:从NameNode到DataNode的完整链路

HDFS读写原理与Java API实战:从NameNode到DataNode的完整链路

简介:《云计算技术实验报告四:HDFS文件的读写》是一份计算机科学专业《云计算技术》课程的实验报告,面向正在学习Hadoop生态系统的学生,重点演示HDFS分布式文件系统文件的上传、下载与合并编程实现。资源包共1个文件,为…

2026/10/5 5:01:44 阅读更多 →
HDFS文件读写原理与Java API实战:从架构到实验避坑指南

HDFS文件读写原理与Java API实战:从架构到实验避坑指南

简介:本资源为计算机系《云计算技术》课程配套实验报告,聚焦HDFS分布式文件系统的读写、合并与上传下载实践,适合正在学习Hadoop生态、需要完成同类实验或理解HDFS编程接口的高校学生。报告完整展示了在Linux环境下安装Eclipse、配置Hadoop连…

2026/10/5 5:01:44 阅读更多 →
MRAM与PIC32工业存储方案:MR25H40CDF驱动与可靠性设计

MRAM与PIC32工业存储方案:MR25H40CDF驱动与可靠性设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 5:01:44 阅读更多 →
一键开关机芯片选型指南:从按键逻辑到待机功耗的四个维度

一键开关机芯片选型指南:从按键逻辑到待机功耗的四个维度

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 5:01:44 阅读更多 →
Ubuntu下OpenOCD与GDB联合调试STM32:从命令行到断点的完整实战

Ubuntu下OpenOCD与GDB联合调试STM32:从命令行到断点的完整实战

“一键调试”按钮的背后:Ubuntu下OpenOCD与GDB的联合调试如果你用过STM32CubeIDE、Keil或者IAR,你大概率从来没有直接碰过OpenOCD和GDB。你看到的只是一个“Debug”按钮,点了之后程序就跑起来了,断点也停了,一切顺理成…

2026/10/5 5:00:44 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 3:06:17 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 11:40:45 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 20:14:29 阅读更多 →