别再用new ObjectMapper()!Jackson实例复用与性能优化之道

第 N 次看到new ObjectMapper()出现在业务代码里,我实在忍不住了。今天想把这件事一次说透:ObjectMapper 不能当成普通工具对象随手 new,它是个典型的重量级组件,每次 new 都在烧 CPU、堆内存和 GC 停顿。文章的后半部分会给出线程安全分析、共享实例的标准写法,以及哪些“边界场景”确实可以创建第二个实例。

1. 第 N 次看到 new ObjectMapper 后,我决定认真算一算

1.1 一个典型反面代码长什么样,为什么会出现在 Review 里

先说一个我在代码评审里见惯了的样子:

public class OrderCallbackParser { public PayResult parse(String body) throws JsonProcessingException { return new ObjectMapper() .readValue(body, PayResult.class); } }

语法上完全没毛病,编译能过,单测能过,线上跑一段时间也不一定立刻炸。问题就出在“不一定立刻炸”这几个字上。以为节省了定义变量的两行代码,实际上每次调用都把整个 JSON 处理链路从头组装一遍。

为什么这类代码这么多?我复盘过几个原因。第一,官方文档和很多入门示例为了降低理解门槛,第一行永远是ObjectMapper mapper = new ObjectMapper(),读者照抄之后习惯把它当成“new 一个 StringBuilder”那种级别的东西。第二,IDE 的自动导入和自动补全进一步把人往这条路上引。第三,也是最隐蔽的——责任错位。写业务的人只关心“把 JSON 变成对象”,至于 ObjectMapper 的初始化和生命周期,被默认交给了调用点,于是每个方法都顺手 new 一个。

这种写法的本质问题不是“代码不优雅”,而是“把重量级资源的构建成本放进了高频调用路径”。

1.2 被忽略的二重成本:CPU 与 GC

先说 CPU。ObjectMapper 不是一件衣服,它是整套“加工厂”。每次 new 都会重新建立序列化器查找表、反序列化器缓存、类型解析器、模块注册链。你以为只是new一个对象,实际上是把一套加工流水线完整地推倒重盖了一遍。对于单个小 JSON 来说,多出来的耗时可能只有几毫秒甚至更少,但在高 QPS 接口里,这会被放大成一个持续性的 CPU 损耗。

再说 GC。每个 new 出来的 ObjectMapper 都会连带创建一批内部组件:多个 Config、Module 列表、SerializerProvider、ClassIntrospector,还有无数中间对象。这些对象在请求结束后没有人引用,很快变成垃圾。请求量越大,Young GC 越频繁,严重的时候会拖出长尾延迟。

我之前在一个消息网关项目中做过一次简单对照。网关每秒处理上千条报文,每条报文里有一个嵌套三层的数据结构。把反序列化从“每次 new”改成“复用全局实例”后,接口耗时的 P99 明显下降,GC 频率也低了不少。这个项目的改动只涉及一个工具类,五分钟改完,收益却非常直观。

提示:凡是高频调用路径上的“配置类”对象,优先考虑复用;如果同时它又是线程安全的,那就更没有理由每次重建。

1.3 别把“能用”当成“该用”

还有一种辩解是“我们流量小,new 一下无所谓”。这句话放在内部小工具里也许说得通,但放在线上服务里就是在给未来埋雷。流量小不代表永远小,也不代表某个瞬间不会突发。与其等 CPU 告警了再去翻代码找罪魁祸首,不如一开始就养成共享实例的肌肉记忆。

另一个常见误会是“我 new 一个新的,配置之间不会互相影响,最安全”。这个想法真的是太天真了。多个实例意味着每处配置都可能漂移——这个接口漏配了FAIL_ON_UNKNOWN_PROPERTIES,那个接口又忘了注册JavaTimeModule,等到联调时发现同一份 JSON 在不同入口解析结果不一样,排查起来比性能问题更痛苦。统一实例本质上是在帮你统一“契约”。

2. 拆开 ObjectMapper:它内部到底装了多少组件

2.1 从读一个 JSON 到产出对象,缓存起了什么作用

想明白为什么不该 new,得先看它在第一次readValue时做了什么。

模型对象往往长这样:

public class PayResult { private String orderId; private Integer status; private Amount amount; private Long payTime; }

当 Jackson 第一次反序列化PayResult时,ObjectMapper会通过TypeFactory解析目标类型,然后向DeserializationContext请求对应类型的反序列化器。如果没有命中缓存,它就要启动BeanDeserializerFactory去分析类结构:哪些字段、哪些 getter/setter、是否需要@JsonProperty、是否需要自定义反序列化器,最后把整套结果塞进缓存,下次直接从缓存里取。

这个“第一次分析”的过程非常昂贵,因为涉及反射、注解扫描、递归遍历复杂类型。复用一个ObjectMapper,所有模型类的反序列化器只会构建一次;每次 new,这套构建流程就会在不同实例上各自重复一遍。

序列化过程同理。writeValueAsString时会经过SerializerProvider,同样需要把 Java 类型映射成 JsonSerializer,同样有缓存机制。如果你每次 new 一个 mapper,那么每次都是一次“冷启动”,永远吃不到缓存红利。

同一个实例还有一层rootName缓存、classToId缓存等内部结构,这些都能有效缩短常规路径上的查找时间。我实测过的感受是:对于结构体较大、字段较多的对象,冷启动和热调用的差距非常明显,远不止几微秒。

2.2 “默认实例”不等于“完整功能实例”

很多人以为new ObjectMapper()就是“开箱即用”的完整版。实际上,Jackson 的核心 jar 默认只覆盖最基础的数据类型。Java 8 的LocalDate、LocalDateTime、Instant,如果不额外注册JavaTimeModule,直接序列化得到的基本就是序列化后的字符串或者直接抛异常。

此外,很多项目还会用ParameterNamesModule来支持基于参数名的反序列化,用自定义 Module 处理某些第三方类型。你每 new 一次,就得把这些模块重新注册一遍。注册没做齐,跑出来的结果就是“本地好好的,测试环境突然类型不对了”。

正确的思路是:把“完整功能”配置在唯一的一个实例上,然后所有代码都向这个实例要能力。这样,需要加新模块时,只改动一处,所有调用方自动生效。

2.3 手写 new 的隐藏风险:一直没配置到位

每次 new 还给“配置漂移”开了方便之门。举个例子,A 同学在订单服务里 new 了一个 mapper,并且手动调了configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)。B 同学在支付回调里也 new 了一个,但他没调这个配置。于是同一个接口,A 能解析前端多传的字段,B 直接抛异常。两个服务明明用的是同一个 jar,行为却不一样。

这种问题一旦出现,排查起来特别让人崩溃。因为代码各自看起来都挺正常,最终只能靠人工对比每个 mapper 的配置差异。

统一共享实例之后,配置只存在一个地方。规则是什么,全体执行什么,不需要给每个入口重复讲解。

3. 正确姿势:共享实例的线程安全性到底靠不靠谱

3.1 Jackson 文档说的“线程安全”指什么边界

很多人不敢共享实例,是因为心里有个疑问:“多个线程同时用它,会不会出问题?”

答案是可以共享,但有个前提:在完成配置之后、进入并发使用阶段,不再修改这个实例的配置状态。Jackson 的ObjectMapper内部使用不可变配置和并发缓存来处理读写操作。所有序列化器/反序列化器的缓存都是可以安全并发访问的,读取和写入操作在实例上是线程安全的。这个设计就是冲着“一次构建、无限复用”去的。

真正不安全的是什么?是“一边用一边改配置”。比如某个线程在请求生命周期里调用mapper.setPropertyNamingStrategy(...),另一个线程同时在用同一个 mapper 解析另一段 JSON,那结果就无法保证了。正确做法是把所有配置放到启动阶段或者字段初始化阶段,运行期间不再调用任何 setter。

我把这个边界总结成一句口诀:配置期独占,使用期只读。只要守住这条,共享实例的安全性和复用的效率可以兼得。

3.2 让配置固化:常见共享写法对比

共享实例最常见的写法有三种。第一种是工具类中的静态常量,适合无框架的老项目:

public final class JsonSupport { private static final ObjectMapper MAPPER = JsonMapper.builder() .serializationInclusion(JsonInclude.Include.NON_NULL) .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .addModule(new JavaTimeModule()) .build(); public static <T> T read(String json, Class<T> clazz) throws JsonProcessingException { return MAPPER.readValue(json, clazz); } public static String write(Object obj) throws JsonProcessingException { return MAPPER.writeValueAsString(obj); } private JsonSupport() { } }

第二种是 Spring Boot 环境下的容器托管:

@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { return JsonMapper.builder() .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .serializationInclusion(JsonInclude.Include.NON_NULL) .addModule(new JavaTimeModule()) .build(); } }

第三种是既有 Spring 自动配置、又需要定制少量特性的团队,推荐用Jackson2ObjectMapperBuilderCustomizer来追加配置,而不是再 new 一个新的 mapper 把 Spring 默认实例覆盖掉,避免影响 MVC 消息转换等内置链路。

静态常量的优点是简单直接,缺点是不适合依赖注入。容器托管的优点是生命周期统一,也方便测试时替换。最不推荐的一种是“每个 Service 里面定义一个ObjectMapper mapper = new ObjectMapper()”,那跟方法内 new 没有本质区别。

3.3 我踩过的坑:在运行期给共享实例“加料”

有一次,为了给某个管理后台临时返回一个特殊视图,我不想改 DTO,就在请求处理方法里直接调用了mapper.writerWithView(...)。这个没问题,因为writerWithView返回的是新的 writer 实例。真正有问题的是另一段代码:有人在修改一个遗留接口时,直接在调用链路上执行了mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false),当时看满足了这个接口的需求,结果把全站共享实例的配置也改了。从那以后,其他接口遇到未知字段都不报错了,数据质量问题被掩盖了很久才发现。

这就是共享实例的最大敌人:不经评审、不固定时机的配置变更。现在我定了一个规矩:

  • 所有修改 mapper 配置的代码只允许出现在启动阶段或 Bean 初始化阶段;
  • 运行期需要派生能力时,一律通过reader()/writer()创建变体对象;
  • 任何对ObjectMapper的configure、enable、disable、registerModule调用,都要加注释说明归属。

只要大家守住这个约定,共享实例就是最省心的方案。

4. 边界场景:什么时候确实需要第二个 ObjectMapper

4.1 同一 JVM 里需要两套互斥的命名策略

并不是说全项目只有一个 ObjectMapper 才是对的。共享实例的前提是“配置统一”,如果两条业务线对 JSON 风格的约定都南辕北辙,强行共用一个实例反而会制造混乱。

我遇到过这样一个项目:对内模块之间统一使用驼峰命名;对外对接的旧客户端只接受蛇形命名。如果只用一个 mapper,要么外发接口手动写一堆@JsonProperty,要么内部接口全都变成蛇形,两边都别扭。

这时候创建两个 ObjectMapper 是合理的设计:

@Configuration public class DualJacksonConfig { @Bean public ObjectMapper camelCaseMapper() { return JsonMapper.builder() .propertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE) .build(); } @Bean public ObjectMapper snakeCaseMapper() { return JsonMapper.builder() .propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE) .build(); } }

关键在于:第二个实例的“诞生理由”必须是一个明确且长期存在的配置分歧,而不是临时偷懒。如果你需要两套配置,那就让它们各司其职,同时写清楚各自服务的协议线。

4.2 模块注册冲突,全局唯一实例反而成了“全局污染”

有时候不是你想建多个实例,而是第三方库非要往全局 mapper 里塞模块。常见的例子是某些框架在启动时自动注册自定义 Module,把你辛苦配置的FAIL_ON_UNKNOWN_PROPERTIES=false或者序列化包含策略给改掉。

冲突之后,最直接的做法就是让框架使用自己定义的实例,而不是去动那个被污染的全局实例。这种情况下,为某个隔离区域单独创建一个 mapper,是一种防御式设计,合理且必要。

但这种“防御式实例”一定要控制在最小范围。比如只让某个HttpMessageConverter使用额外创建的 mapper,而不要所有接口都去 new 一个自己的。范围越大,日后维护成本越高。

4.3 不想破坏共享实例的临时变体用法

更多时候,你需要的并不是第二个 ObjectMapper,而是“同一配置下的临时变体”。

比如同样一段对象,大部分接口统一排除 null 字段,但导出报表时希望保留所有字段。这时候不应该去改共享实例的serializationInclusion,正确做法是:

ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter(); String result = writer.writeValueAsString(reportData);

又比如某个接口只想解析某几个字段,可以用:

ObjectReader reader = mapper.readerFor(TradeDto.class) .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); TradeDto dto = reader.readValue(json);

ObjectWriter和ObjectReader都是从共享 mapper 派生出来的“快照”,拥有独立配置,不影响源 mapper。这个机制非常顺手,可惜很多人不知道,反而去 new 一个全新的 mapper 来实现临时差异。

注意:运行期派生ObjectWriter/ObjectReader是安全的,它们内部保存的是不可变配置快照;但运行期直接修改ObjectMapper本身的 setter 是不安全的。

4.4 分场景使用总结

我梳理了一张表,方便大家对照自己的处境做决定:

场景改共享配置派生 Reader/Writer新建 ObjectMapper
整个系统配置统一永远不要按需用不需要
偶尔需要格式化输出不需要推荐不推荐
个别接口要忽略未知字段不推荐推荐不推荐
两条业务线命名风格不一致会把全局带偏无法根治合理
第三方框架已经污染全局实例不能解决不能解决推荐隔离实例
测试方法里随便跑一下不需要不需要可以接受

表格里唯一可以放开手脚 new 的场景是“测试方法里随手验证一个 JSON 结构”。因为测试生命周期短,没有性能顾虑,也不存在长期维护问题。但即便是测试代码,一旦你会反复用同一个 mapper,还是抽成一个共享常量更方便。

5. 落地清单:把“共享复用”写进团队约定

5.1 Spring Boot 环境下的标准配置姿势

很多团队已经把 Spring Boot 用得很熟了,但在 ObjectMapper 这件事上仍然容易踩坑。最常见的误区是:自己定义了一个很全的 ObjectMapper Bean,却没有意识到它会影响MappingJackson2HttpMessageConverter,也就是 MVC 里所有接口的请求/响应转换器都会用你的这个实例。

这是个优势,也是个责任。优势是一改全改,责任是别把定制对象放进这个全局 Bean 里。合理的做法是让这个 Bean 保持“通用性”,只配置团队统一要求的特性,例如:

@Configuration public class JacksonConfiguration { @Bean public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() { return builder -> { builder.serializationInclusion(JsonInclude.Include.NON_NULL); builder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); builder.modules(new JavaTimeModule()); }; } }

这样 Spring Boot 会负责生成一个统一实例,并且注册到所有该用的地方。如果你在另外的代码里又new ObjectMapper(),那这个 Bean 就白配置了。

5.2 五个容易反复踩中的“new”诱导位

根据我的观察,业务代码里最容易长出new ObjectMapper()的位置就那么几个:

  • 工具类:写着写着就成了new ObjectMapper().readValue(ing),顺手,但要忍。
  • DTO 转换器:比如把某个接口返回值转成另一种结构,为了图省事直接在方法里造一个 mapper。
  • convertValue场景:从一个 Map 转成一个对象,有人不熟悉mapper.convertValue,就干脆 new 一个再readValue。
  • 回调、防抖、消息队列消费等高频入口:这些位置天然是性能敏感区,偏偏最容易写 new。
  • 测试基类:每个测试方法都去 new,测试代码量一大,浪费也很客观。

我建议在代码评审时直接亮一条规则:凡是出现new ObjectMapper()的地方,必须能回答两个问题——这个实例的生命周期由谁管理?为什么不能复用程序中已有的统一实例?答不上来,就改成共享引用。

5.3 用最小改动把旧代码收敛到统一实例

老项目里已经到处是new ObjectMapper()怎么办?不用搞大重构,可以分三步收敛:

第一步,先在一个稳定的公共类里定义共享实例,比如JsonSupport.MAPPER或 Spring Bean。

第二步,把工具类里最核心的几个readValue/writeValueAsString调用改成使用共享实例,这些是调用量最大、收益最高的地方。

第三步,清理剩余散点。用 IDE 的全局搜索把所有new ObjectMapper()列出来,按调用频率排序,高优先级的先改。遇到实在要新建的,一定要在注释里写明理由。

这套做法的好处是:每一次改动都是小步提交,风险可控,收益却会随收敛比例逐步显现。我有一次改造一个老网关,第一天只改了核心解析入口,P99 就降下来一截;后面两天把剩余散点全部清掉,效果更明显。

5.4 最后一件事:把“不 new”固化成团队习惯

代码规范这种东西,光写在 wiki 里没人看,最好直接落到评审卡点和工具链上。比如在 CI 里加一个简单的扫描规则,禁止新增的new ObjectMapper()出现在main代码中;或者约定所有 JSON 操作必须经过某个公共入口。

更深一层的思路是:把 JSON 序列化/反序列化能力封装成业务无关的基础组件。这样团队里的同学不需要考虑 ObjectMapper 怎么创建、模块怎么注册,只需要调用统一 API,那里自然隐藏着一个共享实例。当“正确用法”变成“唯一用法”时,就不需要靠自觉来维持了。

以我的个人体会来说,ObjectMapper 的复用和线程安全从来不是“会不会崩”这种二元问题,而是“值不值得”的效率问题。很多人纠结它安不安全,其实真正该问的是:每次 new 带来的冷启动成本、GC 压力、配置漂移风险,是不是我业务愿意承担的。

如果你还没把项目里的 ObjectMapper 收敛干净,建议今天就用搜索框扫一遍。当你把第一个高频入口改成共享实例后,再看那条耗时长尾,会非常直观地感受到“配置一次、复用到底”带来的差异。以后在代码里再看到有人写new ObjectMapper(),就可以把这篇内容甩给他:这个对象,真的不是给你这么玩的。

相关新闻

OpenFeign声明式调用核心机制与生产实践:代理、超时、连接池、拦截器

OpenFeign声明式调用核心机制与生产实践:代理、超时、连接池、拦截器

最近在梳理微服务调用这块的内容&#xff0c;发现很多团队的调用链路里都藏着OpenFeign的身影。这组件用起来确实方便——接口一声明&#xff0c;远程调用就跟调本地方法一样。但真到排查问题的时候&#xff0c;不少人会卡在"它到底是怎么把接口变成可用对象的""…

2026/10/20 18:49:51 阅读更多 →
KMeans预筛+KNN精判:解决小样本高维医疗数据分类难题

KMeans预筛+KNN精判:解决小样本高维医疗数据分类难题

简介&#xff1a;本资源是一份面向机器学习初学者与课程设计实践者的乳腺癌分类预测完整方案&#xff0c;聚焦KMeans聚类与KNN分类协同建模&#xff0c;解决医学数据中良恶性二分类预测问题&#xff0c;适用于本科机器学习、数据挖掘类课程设计及算法实战训练。压缩包共5个文件…

2026/10/20 18:49:51 阅读更多 →
LLaMA-Factory实战:从数据准备到LoRA微调完整指南

LLaMA-Factory实战:从数据准备到LoRA微调完整指南

把跑通微调的经验沉淀一下,是个挺磨人的过程。我最初是拿现成脚本改,改来改去总会遇到数据格式不对、学习率不合适、一爆显存就得重新来一遍这类问题。后来换到LLaMA-Factory,整体链路才算是理顺了——数据准备、模型加载、LoRA训练、评测、推理、导出合并,它基本都替你封装好了…

2026/10/20 18:49:51 阅读更多 →

最新新闻

数据结构(笔记)——顺序栈

数据结构(笔记)——顺序栈

1.顺序栈的定义顺序栈是 栈的一种顺序存储结构&#xff0c;即用 一段连续的存储空间&#xff08;通常是数组&#xff09;来实现栈。 栈的特点是 先进后出&#xff08;LIFO, Last In First Out&#xff09;&#xff1a;只能在一端&#xff08;称为栈顶 Top&#xff09;进行插入和…

2026/10/20 19:24:51 阅读更多 →
用Steering Files和Kiro Hooks打造AI编程助手的项目记忆系统

用Steering Files和Kiro Hooks打造AI编程助手的项目记忆系统

你有没有这种感觉——同一个AI编程助手&#xff0c;在别人手里像干了十年的老兵&#xff0c;到了你手里&#xff0c;连你上礼拜刚拆分的模块都记不住。每次它都很客气地说“你好&#xff0c;有什么可以帮你”&#xff0c;然后你只能再花十分钟去解释&#xff1a;我们的项目分层…

2026/10/20 19:24:51 阅读更多 →
如何榨干LFM2.5-24B-A2B-Preview-mxfp8的推理能力:Chat Template与max-tokens配置指南

如何榨干LFM2.5-24B-A2B-Preview-mxfp8的推理能力:Chat Template与max-tokens配置指南

【免费下载链接】LFM2.5-24B-A2B-Preview-mxfp8 项目地址&#xff1a; https://ai.gitcode.com/hf_mirrors/mlx-community/LFM2.5-24B-A2B-Preview-mxfp8 点击查看 免费下载 LFM2.5-24B-A2B-Preview-mxfp8 是 Liquid AI 的 MoE 大语言模型的 MLX 量化版本&#xff0c;总参数 2…

2026/10/20 19:24:51 阅读更多 →
信贷风控实战:从数据清洗到风险定价的完整建模流程

信贷风控实战:从数据清洗到风险定价的完整建模流程

简介&#xff1a;2020年全国大学生数学建模竞赛C题“中小微企业信贷决策”实践资料包&#xff0c;包含可编辑Word论文与MATLAB源代码&#xff0c;面向参赛学生、毕业设计者及金融数据分析学习者&#xff0c;系统展示基于统计建模解决企业信贷风险评估的完整流程。压缩包共160个…

2026/10/20 19:24:51 阅读更多 →
C语言终端表格打印库:按字符显示宽度实现中文对齐

C语言终端表格打印库:按字符显示宽度实现中文对齐

简介&#xff1a;终端中以表格形式整齐打印包含中文的字符串&#xff0c;是不少C语言初学者都会遇到的常见痛点。这份示例资源专门解决C语言表格对齐打印问题&#xff0c;在Ubuntu 14.04 64位下完成测试&#xff0c;通过处理中文字符显示宽度&#xff0c;避免了字符错位&#x…

2026/10/20 19:24:51 阅读更多 →
音视频服务为何是互联网的终极压力测试仪

音视频服务为何是互联网的终极压力测试仪

1. 为什么“音视频服务”是互联网真正的压力测试仪你有没有试过在地铁里点开一个4K直播&#xff0c;画面卡成PPT&#xff0c;而旁边的人刷短视频却丝滑如初&#xff1f;或者深夜和朋友连麦打游戏&#xff0c;语音断断续续&#xff0c;但微信文字消息秒回&#xff1f;这些不是玄…

2026/10/20 19:23:50 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →