APK加固与伪加密:从DEX加密原理到自研壳实践
简介这是一套面向安卓开发者与安全测试人员的APK加固与伪加密完整工程包解决应用被反编译、二次打包等常见风险。资源共92个文件涵盖Java加壳工具源码、安卓加壳工程、Demo源程序、签名配置文件、构建脚本及说明文档等通过工程模块清晰区分加壳端与应用端方便对照学习与二次改造。压缩包约3.25MB轻量易用开发者只需在ant.properties中配置自有签名key即可运行build.xml生成并安装测试。资源包内包括Class、Java、XML、APK、JAR等类型文件分别对应源码逻辑、资源布局、打包产物与辅助工具便于按需查阅。目前已有2515人学习下载适合具备一定安卓逆向或开发基础、希望快速掌握防逆向手段的读者作为入门实操参考。1. 为什么“伪加密”只是门槛加壳才是重头戏做过 APK 反编译对抗的开发者基本都经历过这一幕拿到一个 APK扔进 jadx 准备看代码结果要么提示解析失败要么打开后只有几个壳的入口类真正的业务逻辑连影子都找不到——这就是加壳最常见的“整包加固”效果。而伪加密则是更取巧的一招它只是改掉 ZIP 结构里的几个标记位让反编译工具的解析过程直接报错成本极低但也极易被绕过。把这两个概念放在一起看本质是在讲一件事APK 作为 ZIP 压缩包和 DEX 字节码的双重结构恰好存在两层可攻击的防御面。本文会先从 DEX 加载和 ZIP 解析两条线讲清楚底层原理再带你手写一个最小可运行的加固壳接着给出三种伪加密的具体做法最后落到方案选型和验证清单。适合做 Android 安全研究入门、应用分发前自保护、以及想评估加固成本的技术负责人阅读。2. 先搞懂加壳的底层逻辑从 DEX 字节码到类加载的攻防链2.1 反编译的第一步是解析 DEX加壳的本质是让解析器找不到真身APK 里真正包含业务代码的是classes.dex反编译工具jadx、apktool、dex2jar的工作流程都是先把 DEX 解析成可读的类结构再还原成 Java 或 Smali 代码。如果直接拿到未加固的 APK等于把源代码以字节码形式完整交了出去混淆只能提高阅读门槛类名和方法名变成 a、b、c但逻辑关系依然清晰可读。加壳的出发点与混淆完全不同。壳程序会在 APK 原始 DEX 文件被解析之前介入先把真正的 DEX 文件加密或者隐藏到其他位置比如 assets 目录、so 文件末尾同时将一个壳的入口 DEX 替换到正常位置。反编译工具拿到的只有壳的入口类想继续跟进时才发现那只是一个空壳于是逆向链路在此断裂。这就是“加壳”这个名字的来源——给原始 DEX 包了一层壳只有壳代码知道怎么把里面的内容取出来。运行时机上系统安装 APK 后启动应用首先执行的入口是 Application 类。壳的入口 Application 会抢在原始业务代码加载前完成解密、释放 DEX、注册类加载器这一整套动作然后再把流程交还给真正的业务逻辑。所以加壳方案至少由三个部分组成加密后的原始 DEX、壳入口类、负责运行时解密和加载的动态库或纯 Java 实现。2.2 两种主流壳形态对比整包加固与函数抽取整包加固是最经典的做法也是本文手写方案会采用的方式。它的核心逻辑是把整个 DEX 文件加密后藏起来运行时一次性解密并加载。优点是可以复用的成熟代码多原理直观兼容性相对好缺点是 DEX 一旦加载进内存整个过程是“整块暴露”的熟练的逆向者可以直接从内存中 dump 出完整 DEX脱壳工具正是基于这个思路工作的。函数抽取加固是针对整包加固被脱壳问题的升级方案。它不再整体加密 DEX而是把每个方法的关键指令片段CodeItem 部分抽取到外部文件中运行时由壳的 Native 层在方法即将执行时动态补齐。由于内存中永远不存在一份完整的 DEX传统的内存 dump 方式会拿到一个残缺的方法体无法直接还原。但代价同样明显指令补齐发生在每次方法执行时性能损耗大于整包加固而且抽取的范围需要精心选择否则会引发严重的兼容性问题。选择哪种形态取决于你的威胁模型。如果只是防止普通开发者随手拖进 jadx 看逻辑整包加固已经足够如果担心目标是被专业逆向团队的针对性研究需要考虑函数抽取加反调试的组合方案。我一般会建议先做整包加固跑通流程后再评估是否需要升级。2.3 自定义 ClassLoader 加载加密 DEX一个 Application 的生命周期运行时加载加密 DEX 的关键点在Application.attachBaseContext()这是整个流程中调用时机最早的入口早于onCreate()。在这里完成类加载器的替换才能确保后续任何业务类的实例化都经由壳的类加载器完成。常见做法是拿到当前应用 context 的PathClassLoader将它替换为新建的DexClassLoader同时保持两者之间的 parent 关系否则系统框架的类型转换会出问题。加载路径上需要先把解密后的 DEX 释放到应用私有目录比如/data/data/包名/app_odex/某些版本下还要同步释放对应的 ODEX 优化文件这也是后续兼容性问题的集中爆发点。具体到代码层类加载器替换还要处理一些细节如果原始 APK 里有多个 DEXmultidex需要全部解密并加入新的路径释放 DEX 的文件名必须与 APK 内的名称无关否则会被脱壳工具按图索骥解密操作本身要尽量规避监听比如避免使用调试器可追踪的流程这属于进阶加固范畴。理解了这一条链路后面手写最小壳的时候就只需要把每个节点串起来。3. 手写一个最小加固壳隐藏 DEX 并动态加载3.1 准备工作三个工具与一个目标 APK动手写壳之前先确认本机环境。常规做法是准备一台装有 JDK 8 和 Android SDK 的机器再额外安装jadx用于验证加固效果。下面的命令假设你的工作目录是/tmp/demo_shell/并且已经有一个未加固的目标 APK 放在该目录下我们就叫它app_plain.apk。mkdir -p /tmp/demo_shell/decrypted cd /tmp/demo_shell unzip app_plain.apk -d plain_extracted/ ls plain_extracted/# 解压后应至少看到 AndroidManifest.xml classes.dex res/ assets/这一步的目的是把 APK 拆开拿到原始 DEX 文件为后续的加密和重打包做准备。需要注意的是unzip解压会丢失签名信息和 ZIP 对齐标志这些都需要在重打包阶段恢复否则安装时会直接报错。3.2 加密 DEX 并把它塞进 assets拿到classes.dex之后对它进行加密。这里采用 AES 对称加密密钥写死在壳的 Native 层里会更稳妥一点但是最小 Demo 为了方便直接在 Java 层用一个常量字符串表示。注意这一步如果用于生产密钥放在 Java 层等于没有加密这只是为了跑通流程。import os from Crypto.Cipher import AES from Crypto.Util.Padding import pad key b0123456789abcdef # 16字节密钥生产环境需替换 iv babcdef9876543210 with open(plain_extracted/classes.dex, rb) as f: plain_data f.read() cipher AES.new(key, AES.MODE_CBC, iv) encrypted_data cipher.encrypt(pad(plain_data, AES.block_size)) with open(plain_extracted/assets/encrypted.dat, wb) as f: f.write(encrypted_data) print(f原始 DEX {len(plain_data)} 字节 - 加密后 {len(encrypted_data)} 字节)# 预期输出 原始 DEX 3881234 字节 - 加密后 3881248 字节AES 的 CBC 模式要求明文长度是 16 的倍数所以需要做 PKCS7 Padding解密端要对应做 Unpadding。这一步骤的核心目的不是“绝对安全”而是让原始 DEX 在静态层面不再以明文形式出现反编译工具直接解析 APK 文件时只能找到一段密文。参数上值得关注的是密钥长度使用 16 字节对应 AES-12824 字节 AES-19232 字节 AES-256密钥越长越难暴力破解但解密耗时也会增加。3.3 编写壳入口解密 assets 中的 DEX 并加载接下来创建加固 APK 的壳工程其中的 Application 替代原本的入口类。这个类要完成的动作是读取 assets 目录中的encrypted.datAES 解密出原始 DEX 字节写入应用私有目录最后通过DexClassLoader加载。下面是核心代码。// ShellApplication.java public class ShellApplication extends Application { private static final String KEY 0123456789abcdef; private static final String IV abcdef9876543210; Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); try { // 1. 从 assets 读取加密数据 InputStream is getAssets().open(encrypted.dat); ByteArrayOutputStream baos new ByteArrayOutputStream(); byte[] buffer new byte[8192]; int len; while ((len is.read(buffer)) ! -1) { baos.write(buffer, 0, len); } byte[] encryptedData baos.toByteArray(); is.close(); // 2. AES/CBC/PKCS7Padding 解密 Cipher cipher Cipher.getInstance(AES/CBC/PKCS7Padding); SecretKeySpec keySpec new SecretKeySpec(KEY.getBytes(), AES); IvParameterSpec ivSpec new IvParameterSpec(IV.getBytes()); cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); byte[] dexBytes cipher.doFinal(encryptedData); // 3. 释放到私有目录 File dexDir getDir(dex, MODE_PRIVATE); File dexFile new File(dexDir, real_%d.dex); FileOutputStream fos new FileOutputStream(dexFile); fos.write(dexBytes); fos.close(); // 4. 加载并替换类加载器 DexClassLoader loader new DexClassLoader( dexFile.getAbsolutePath(), dexDir.getAbsolutePath(), null, base.getClassLoader()); // 关键替换 Application 的 mBase 里的 mClassLoader replaceClassLoader(base, loader); } catch (Exception e) { // 实际加固壳会在这里做异常兜底并上报 e.printStackTrace(); } } private void replaceClassLoader(Context context, ClassLoader loader) throws Exception { // 反射修改 LoadedApk 中的 mClassLoader 字段 Object loadedApk context.getClass().getMethod(mLoadedApk).invoke(context); Field field loadedApk.getClass().getDeclaredField(mClassLoader); field.setAccessible(true); field.set(loadedApk, loader); } }# 需要手动在 AndroidManifest.xml 中修改 application android:name.ShellApplication ...代码第 1 步到第 2 步是加解密对称过程的逆向写加密脚本时用 AES 加密原始 dex壳里做同样参数的解密。密钥和 IV 都要求与加密脚本完全一致任何一位不匹配都会抛BadPaddingException。第 3 步把解密出的 DEX 写入私有目录文件名里加了时间戳real_%d.dex这是为了放置多个不同加固包的路径冲突。第 4 步的DexClassLoader构造参数中第二个参数是 dex 的优化缓存目录传null会用系统默认路径但在部分低版本系统上会抛异常建议显式传入应用私有目录。replaceClassLoader是整个流程的精髓之一。Android 的 Application 与类加载器是绑定关系如果只创建了DexClassLoader但不替换掉 context 里的 mClassLoader后续业务类加载时依然会走原始的PathClassLoader它不认识资产目录里的 DEX类找不到就闪退。注意这段反射代码在不同版本上的字段名有差异Android 8.0 以后 LoadedApk 中的字段名仍是mClassLoader但在此之前有些版本存储在ActivityThread中需要做分支处理。3.4 重打包与签名顺序错了连装都装不上完成壳的代码后把壳工程编译出的classes.dex、AndroidManifest.xml与 assets 目录下的加密文件合并重新打包为 APK。这里最常翻车的点是 Zipalign 对齐与签名顺序。正确顺序是先 Zipalign再签名如果先签名再对齐V2 签名会被破坏。# 1. 构建壳工程并取出壳的 dex cd shell_project ./gradlew assembleRelease cd .. # 2. 合并文件先清空原 APK 结构 rm -rf merged_apk mkdir -p merged_apk cp -r plain_extracted/* merged_apk/ # 删除原始 classes.dex用壳的 dex 替代 rm merged_apk/classes.dex cp shell_project/app/build/outputs/apk/release/shell_classes.dex merged_apk/classes.dex # 3. 重新压缩为 APK注意不要压缩 assets 中的加密文件 cd merged_apk zip -r -X -0 ../app_shelled.zip assets/encrypted.dat zip -r -X -9 ../app_shelled.zip . -x assets/encrypted.dat # 4. Zipalign 对齐 zipalign -f 4 ../app_shelled.zip ../app_shelled_aligned.apk # 5. apksigner 签名 apksigner sign --ks your_keystore.jks --ks-key-alias your_alias \ --ks-pass pass:your_password \ --out ../app_shelled_signed.apk \ ../app_shelled_aligned.apk# 预期结果 app_shelled_signed.apk 生成大小比原 APK 多出几 KB这里的参数有两个关键点。zip -X -0中的-0表示不压缩encrypted.dat因为已经 AES 加密过的数据几乎没有再压缩的空间保留原始存储还能减少运行时解压耗时-X用来去除额外文件属性否则可能影响 v2 签名校验。zipalign 4是 Android 对资源对齐的标准值未对齐的 APK 在 Android 11 以后的系统上可能安装失败。每一步做完都用unzip -l检查一下文件结构能提前暴露路径错误。4. 伪加密让 jadx 直接罢工的三种做法与边界4.1 改 AndroidManifest 的伪加密一张“坏掉的清单”AndroidManifest.xml 在 APK 中不是纯文本而是 Android 自有的二进制 XML 格式。jadx 和 apktool 解析 APK 的第一步都是读取 Manifest 来确定包名、入口 Activity 和服务。针对这个特征有一个非常古老的伪加密思路篡改 Manifest 二进制结构中的字符串池长度字段让解析器在读取包名时发生越界异常或得到异常长度从而中止解析。实现方式不复杂。用十六进制编辑器打开解压出的AndroidManifest.xml找到资源字符串池头部的stringCount偏移 8 字节处32 位整数将值改为远大于实际数量的数字比如原值是 15改成 1000。改动后大部分解析器会尝试读取不存在的字符串数据直接抛异常退出。with open(merged_apk/AndroidManifest.xml, rbw) as f: data bytearray(f.read()) # 字符串池头部偏移 8 字节处为 stringCount32位小端 original_count int.from_bytes(data[8:12], little) data[8:12] (original_count 100).to_bytes(4, little) f.seek(0) f.write(data) print(fstringCount 修改为 {original_count 100})# 效果 jadx 打开 APK 报错: Could not decode manifest这个方法胜在改动极小只需要修改 4 个字节。但它的脆弱性也很明显apktool 的较新版本会优先尝试修复异常字符串池而不是直接放弃解析此外许多逆向工具可以切换到忽略 Manifest 直解 DEX 的模式。所以伪加密更适合作为加壳之外的辅助干扰层单独使用基本不具备防逆向能力。4.2 ZIP 伪加密修改 bit flag 让解压工具报错另一种更通用的伪加密作用于 ZIP 文件结构本身。APK 本质是 ZIPZIP 的本地文件头Local File Header中有一个 2 字节的通用位标志General Purpose Bit Flag其第 0 位为 1 时表示该文件条目使用了密码加密。把某个条目对应的 bit 位从 0 改为 1压缩包结构上就“看起来”存在加密解压工具会弹出密码框或直接报错。import struct def pseudo_encrypt(path, target_entry): with open(path, rb) as f: data bytearray(f.read()) # 定位本地文件头签名 0x04034b50 pos 0 count 0 while pos len(data) - 4: if data[pos:pos4] bPK\x03\x04: # 通用位标志偏移为 6占 2 字节 flags struct.unpack(H, data[pos6:pos8])[0] data[pos6:pos8] struct.pack(H, flags | 0x01) count 1 pos 1 with open(path, wb) as f: f.write(data) print(f已修改 {count} 个文件头) pseudo_encrypt(app_shelled_signed.apk)# 效果 unzip app_shelled_signed.apk # 报错: need password / encrypted file运行后 APK 签名校验会直接失败因为 APK 内部的每个文件摘要已经改变。所以 ZIP 伪加密的正确使用方式不是在加固流程后修改而是在重打包、签名之前对 APK 内部的部分条目通常是 dex 或资源设置伪加密位。毫秒级实现成本是它最大的优势但同样因为实现过于简单主流反编译工具早就内置了“忽略伪加密位”的选项字节级别上不具备任何安全性。4.3 伪加密的边界为什么我说“伪”永远是辅助手段伪加密在安全社区被当作一种干扰脚本化逆向分析的手段它可以消耗攻击者的时间增加自动化反编译流程的失败率但挡不住一个愿意花 10 分钟手动处理的逆向者。根本原因是它们没有改变 APK 的可解析本质只是让解析器“暂时找不到”或“误以为需要密码”原始 DEX 依然明文躺在压缩包里。把伪加密和真加壳串联起来的作用在于反编译工具先被伪加密干扰处理完这层障碍后又遇到壳入口双重壁垒可以拦掉绝大多数只想“随手看看”的尝试者。还有一个隐性边界是软件兼容性。伪加密字节修改很容易让 Android 系统的 PackageManager 拒绝安装因为系统在解析 APK 时会同样执行 ZIP 结构完整性检查。我实验下来比较稳妥的位置是只对assets/下的自定义资源文件施加伪加密位不去碰 DEX、Manifest 和资源索引表这样安装不受影响但像 jadx 这类工具在解压时依然会报错中断。不过这种做法对 APK 体积影响小不影响加载性能适合做长期保留的干扰层。5. 加固方案选型与避坑从自研壳到商业加固的参数对比5.1 三类加固方案的适用边界自研壳适合安全要求中等、团队有 Android 底层开发能力的场景。它的优势是完全可控不依赖第三方代码逻辑可以被修改成任何形态劣势是兼容性维护成本极高Android 版本更新会导致反射字段变化、ART 编译策略调整等问题需要专人持续跟进。用一个开发者的周期估计从跑通到稳定覆盖主流机型大约需要两到三个月。开源壳项目是自研和商业方案之间的折中选择。社区中有一些成熟的开源加壳示例可以直接借用其解密流程和类加载逻辑省掉从零调研的时间。但开源壳普遍缺乏适配投入New API Level 出现后往往要自己补丁维护。用它做 Demo 和内部工具完全够用建议不要直接用在对外分发的高价值应用上。商业加固的核心卖点不是“解密算法更强”而是兼容性覆盖和各种反调试特性的持续更新。主流商业方案通常包含 DEX 加固、SO 加固、资源加固、VMP虚拟机保护和反调试配合控制台可以一键完成多渠道包加固。缺点是需要将 APK 上传到第三方的服务器涉及代码泄露的信任问题纯私有化部署版本则价格较高。对比维度 自研壳 开源壳 商业方案 成本 约 2-3 人月 低仅接入成本 按年付费价格差异大 兼容性 需自行适配 依赖社区更新 由厂商负责 反调试 可定制需自己写 通常没有或较弱 内置多种 可对抗性 取决于实现深度 较弱 较强且持续更新 适用场景 内部工具、Demo 学习研究、内部发行 对外发布的高价值应用5.2 避坑记录签名校验闪退、崩溃堆栈乱成一团、渠道包全挂踩坑 1加固后一启动就闪退日志显示ClassNotFoundException。原因通常是 Application 替换和类加载器替换的时机不对DexClassLoader在attachBaseContext中构建时base.getClassLoader()返回的类加载器 parent 关系还没有被完全初始化导致加载的类与系统类冲突。解决办法在替换类加载器时显式指定 parent 为ClassLoader.getSystemClassLoader()并检查当前目录权限。踩坑 2腾讯 Bugly 或自建崩溃平台上报的堆栈全是壳的类名看不到真实业务方法。原因是加固后崩溃时读取的调用栈映射关系已经改变需要厂商提供的符号还原表Mapping 文件做堆栈还原。自研壳需要在打包时记录内存地址与前缀的映射关系崩溃调研时做离线还原商业方案则一般在控制台直接选择“堆栈还原”即可。踩坑 3使用 V2 签名后加固包的安装成功率降低部分低版本机型提示“安装包无效”。原因是某些加固方案在重打包时破坏了 ZIP 中央目录结构或者对 V2 签名的 Block 处理不当。解决时优先选择保留 V2 签名的加固流程自研壳在重打包阶段务必使用apksigner校验最终产物命令为apksigner verify --verbose app_shelled_signed.apk。踩坑 4在 Android 12 以上版本直接加载释放到外部存储的 DEX 会触发 SELinux 限制。现象是释放文件后读取正常但DexClassLoader加载时报Permission denied。解决方式是把释放目录限定在应用私有目录内getDir或getFilesDir并确认 dex 文件 owner 是应用自身不要设置全局可读权限。踩坑 5加固后的 APK 在部分渠道要求修改包名或添加渠道标记直接重打包导致原有加固失效。原因是渠道包需要在加固前进行多渠道标识注入加固后再次修改任意文件都会触发壳的完整性校验。正确的做法是在加固前完成所有渠道配置加固流程只负责加密不参与渠道定制。6. 验证加固结果一套从安装到反编译的自测清单做完加固不是 APK 能装能跑就结束了验证链要闭环到“逆向者视角能拿到多少东西”。我每次都会准备一台干净的 Android 模拟器和两台不同品牌真机执行这样一套自测流程先安装加固后的 APK确认业务功能完整再分别用 jadx、apktool 打开同一个包记录它们各自的报错信息和可输出的内容最后把 APK 解压检查 DEX 目录下是否留存明文代码。具体的自测命令很简单但维度要覆盖全。安装失败属于阻断性问题需要百分百通过反编译工具能否还原出完整代码是加固有效性的核心指标运行时崩溃则要检查堆栈还原能力否则线上问题无法定位加固等于给运维挖了坑。# 1. 安装测试 adb install app_shelled_signed.apk # 2. 反编译测试预期 jadx 无法还原业务代码 jadx -d decompiled_out app_shelled_signed.apk cat decompiled_out/sources/com/yourpackage/MainActivity.java # 3. 文件结构检查 unzip -l app_shelled_signed.apk | grep classes.dex # 4. 崩溃堆栈还原测试 adb logcat | grep AndroidRuntime# 期望结果 1. 安装成功应用正常启动 2. jadx 输出只有壳入口无业务逻辑 3. classes.dex 为壳的入口 dex业务 dex 位于 assets/encrypted.dat 4. 人为制造一次崩溃堆栈需要能够映射到真实业务方法这套验证之外还有一个容易被忽略的检查项包体积增量。加固本身会带来约 100KB 到 1MB 的壳代码和加解密逻辑开销如果增量过大要考虑是否错误地把整份资源也做了加密。另一点是启动耗时加壳应用的冷启动比原始包多出解密与加载 DEX 的时间通常在 100ms 到 300ms 范围内超过 500ms 就说明解密逻辑需要优化比如换用 Native 层解密或延迟按需加载。我自己维护加固方案时有个习惯每次 Android 大版本更新都要重新跑一遍整套自测清单并把失败项的修改时间记录下来。这样做能精确掌握兼容性债的利息增长速度也能在引入新特性前评估加固是否还有必要保留。希望这份验证清单能帮你建立同样的信心——加固方案的稳定性和安全性从来不是靠宣称的而是靠每一次实测盯出来的。本文还有配套的精品资源点击获取

相关新闻

使用 Teachable Machine 训练图像分类模型并在 p5.js 中集成:ml5.js 完整实战指南

使用 Teachable Machine 训练图像分类模型并在 p5.js 中集成:ml5.js 完整实战指南

教程文档示例工程 【免费下载链接】website-archive Archive of the Coding Train website (first version) 项目地址: https://gitcode.com/gh_mirrors/we/website-archive 点击查看 免费下载 本教程围绕 The Coding Train 的「Teachable Machine: Images」视频展…

2026/10/13 7:09:57 阅读更多 →
黑黄配色商务PPT模板设计实操:母版、版式与兼容性维护

黑黄配色商务PPT模板设计实操:母版、版式与兼容性维护

简介:这款黑黄配色商务报告PPT模板专为职场商务汇报场景设计,适合需要快速制作工作概况、阶段成就、经验教训或阶段计划等内容的用户选用。模板以黑色为底、黄色高亮,兼顾稳重感与信息突出度,内置目录页、数据图表、图片展示页等常…

2026/10/13 7:09:57 阅读更多 →
Spring Boot自动配置机制:Spring.factories文件解析与实践

Spring Boot自动配置机制:Spring.factories文件解析与实践

1. Spring.factories 文件解析与应用场景Spring.factories 是 Spring Boot 自动配置机制中的关键配置文件,它采用 Java 的 SPI(Service Provider Interface)机制实现模块化扩展。这个文件通常位于 META-INF 目录下,格式为键值对形…

2026/10/13 7:09:57 阅读更多 →

最新新闻

SQL UNIQUE约束详解:原理、数据库差异与防重复设计实践

SQL UNIQUE约束详解:原理、数据库差异与防重复设计实践

1. UNIQUE约束到底是什么,为什么你需要它做数据库设计这些年,我见过太多因为“忘记加唯一约束”而崩溃的业务系统。最典型的场景:用户注册接口被脚本刷了一遍,username重复了;订单表里同一笔订单被回调程序insert了两次…

2026/10/13 7:55:19 阅读更多 →
Agent-Skills:智能体原子化能力的设计与工程实践

Agent-Skills:智能体原子化能力的设计与工程实践

1. “agent-skills”不是新词,而是智能体能力体系的命名共识 最近在多个技术社区、开源项目文档和内部架构评审会上,“agent-skills”这个组合词出现频率陡增——它既不指代某个具体开源库,也不是某家公司的私有协议,而是一类设计…

2026/10/13 7:55:19 阅读更多 →
Flink DataStream与Table API转换实战:Schema推导、时间属性与常见避坑指南

Flink DataStream与Table API转换实战:Schema推导、时间属性与常见避坑指南

做实时数据处理这几年,Flink的DataStream和Table API来回切换是我用得最频繁的操作之一。刚接触那会儿,总觉得这两套API是两套独立的体系,流上处理业务逻辑用DataStream,做统计查询用Table,中间隔着一道说不清的墙。后…

2026/10/13 7:55:19 阅读更多 →
LiteLLM:大模型API统一网关与智能路由实战指南

LiteLLM:大模型API统一网关与智能路由实战指南

1. LiteLLM不是另一个大模型,而是一把“万能适配器”最近在几个技术群和开源社区里,频繁看到有人发问:“LiteLLM到底是个啥?是又一个新模型吗?”“它和Ollama、LM Studio有什么区别?”——这种误解非常典型…

2026/10/13 7:55:19 阅读更多 →
LiteLLM:大模型API统一接入与智能路由实战指南

LiteLLM:大模型API统一接入与智能路由实战指南

1. 为什么“litellm”突然在开发者圈里被高频提及——它不是新模型,而是新范式最近两周,在多个技术社区、内部分享会和开源项目讨论区里,“litellm”这个词出现的频率明显升高。它不像Llama、Qwen或Claude那样代表一个具体的大语言模型&#…

2026/10/13 7:55:19 阅读更多 →
开源代码审查实战:流程设计、工具配置与团队落地方法

开源代码审查实战:流程设计、工具配置与团队落地方法

代码审查这事儿,我过去几年一直想好好聊一聊。初看上去,open-code-review 这个项目标题没什么特别,好像就是把自己团队做代码评审的过程、工具和规范整理出来,开源给社区用。但如果真这么理解,那就有点浪费了。代码审查…

2026/10/13 7:54:17 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →