热修复

Android热修复原理(一)热修复框架对比和代码修复 相关文章 解析ClassLoader系列 前言 在Android应用开发中,热修复技术被越来越多的开发者所使用,也出现了很多热修复框架,比如:AndFix、Tinker、Dexposed和Nuwa等等。如果只是会这些热修复框架的使用那意义并不大,我们还需要了解它们的原理,这样不管热修复框架如何变化,只要基本原理不变,我们就可以很快的掌握它们。这一个系列不会对某些热修复框架源码进行解析,... 阅读详情

【关于tinker的详细接入请看我的这篇文章】https://blog.youkuaiyun.com/Checkiming/article/details/85223118

Why use thermal fixes?
我们平时遇到刚上线不久的项目APP的bug崩溃或者影响用户体验的话,如果按照通常做法,那就是程序猿加班搞定bug,然后测试,重新打包并发布。这样带来的问题就是成本高,效率低。于是,热修复就应运而生.

What is HotFix?
HotFix(热修复)是针对某一个具体的系统漏洞或安全问题而发布的专门解决该漏洞或安全问题的小程序,通常称为修补程序

传统
这时候我们通常的处理流程是:解决bug、重新打包App、测试、向各个应用市场和渠道换包、提示用户升级、用户下载、覆盖安装。有时候仅仅是为了修改了一行代码,也要付出巨大的成本进行换包和重新发布,而且你难道不站在用户的角度看看这件事?这件事对于用户体验难道不糟糕吗? ̄へ ̄

初级解决方式:
在移动 App 开发里,可以动态部署达到热修复。例如某页面出现了 Bug ,后台服务器修改配置为采用 React Native 显示此页面,而有 Bug 的 Native 页面就隐藏了。等到下一次版本更新发到线上渠道,再采用 Native 展示此页面。

热修复的驳论:

  • 运行时修复不用等待App重新启动,要是需要重启的话,就是冷修复了
  • 发到线上的客户端,是没法及时修改的,但是服务器可以随时控制
  • Deposed 和 Fix 都不能全部适配,各自的方案都有自己的优缺点,classloader 可以发挥更好用途,局部的更新倒是采用 andfix 这样类型的方案,感觉比较方便。

###Android虚拟机原理初读 **
一、ClassLoader
Android中的虚拟机 Dalvik/ART VM 不同于Java的JVM,二者之间的区别 当然这不是今天所要谈及的重点,我们只需辨别Dalvik/ART VM 虚拟机加载类和资源也是要用到ClassLoader,不过Jvm通过ClassLoader加载的class字节码,而Dalvik/ART VM通过ClassLoader加载则是dex就够了。
Android中的类加载器
ClassLoader**分为两种,PathClassLoader和DexClassLoader,两者都继承BaseDexClassLoader

PathClassLoader代码位于libcore\dalvik\src\main\Java\dalvik\system\PathClassLoader.java

DexClassLoader代码位于libcore\dalvik\src\main\java\dalvik\system\DexClassLoader.java

BaseDexClassLoader代码位于libcore\dalvik\src\main\java\dalvik\system\BaseDexClassLoader.java

其中PathClassLoader是用于加载系统类和应用类
DexClassLoader则是用来加载jar、apk、dex文件(加载jar、apk最终也是抽取里面的Dex文件进行加载。)
ClassLoader

**二、热修复机制 **
利用dexElements的顺序来做文章,当一个补丁的patch.dex放到了dexElements的第一位,那么当加载一个bug类时,发现在patch.dex中,则直接加载这个类,原来的bug类可能就被覆盖了

PathClassLoader 代码

public class PathClassLoader extends BaseDexClassLoader {

    public PathClassLoader(String dexPath, ClassLoader parent) {
        super(dexPath, null, null, parent);
    }

    public PathClassLoader(String dexPath, String libraryPath,
            ClassLoader parent) {
        super(dexPath, null, libraryPath, parent);
    }
} 

DexClassLoader代码

public class DexClassLoader extends BaseDexClassLoader {

    public DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent) {
        super(dexPath, new File(optimizedDirectory), libraryPath, parent);
    }
}

可以看出这两个ClassLoader类几行代码就调用了父类的构造函数

public class BaseDexClassLoader extends ClassLoader {
    private final DexPathList pathList;

    public BaseDexClassLoader(String dexPath, File optimizedDirectory,
            String libraryPath, ClassLoader parent) {
        super(parent);
        this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
        Class c = pathList.findClass(name, suppressedExceptions);
        if (c == null) {
            ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);
            for (Throwable t : suppressedExceptions) {
                cnfe.addSuppressed(t);
            }
            throw cnfe;
        }
        return c;
    }

热修复方案比较
其中AndFix可能是接入最简单的一个(和Tinker命令行接入方式差不多),不过兼容性还是是有一定的问题的;QZone方案对性能会有一定的影响,且在Art模式下出现内存错乱的问题(其实这个问题我之前并不清楚,主要是tinker在MDCC上指出的);美团提出的思想方案主要是基于Instant Run的原理,目前尚未开源,不过这个方案我还是蛮喜欢的,主要是兼容性好。

这么看来,如果选择开源方案,tinker目前是最佳的选择,tinker的介绍有这么一句:

Tinker已运行在微信的数亿Android设备上,那么为什么你不使用Tinker呢?

目前较为热门的热修复技术有
阿里的Xposed、AndFix、QZone(ClassLoader)的方案、美团提出的思想方案(基于Instant Run的原理)以及腾讯的Tinker.

  • 前两个方案思路极其相似,都是通过指针替换掉出Bug的方法、类,不同的是Xposed将需要替换的方法连接到hookedMethodCallback,以它来实现替换后方法的调配,而AndFix就比较简洁粗暴了,直接就是获取需要替换的方法指针,将指针指向修改之后的新的java代码.
  • 相比之下,ClassLoader方案便较为巧妙的多了,他巧妙利用了BaseDexClassLoader的机制,类似于dex分包技术。
  • Proxy/Delegate的方案则是使用ProxyApplication动态加载主程序dex。
    ###Xposed优缺点

优点
1)无需重启就可以达到修复bug的目的
2)多个模块可同时进行安装
3)无需修改任何的APK
缺点
1)需要Android 的root权限
2)Dexposed不支持Art模式(5.0+),且写补丁有点困难,需要反射写混淆后的代码,粒度太细,要替换的方法多的话,工作量会比较大。

###AndFix
①原理:AndFix的原理就是方法的替换,把有bug的方法替换成补丁文件中的方法。

注:在Native层使用指针替换的方式替换bug方法,以达到修复bug的目的。

加载补丁文件
获取补丁方法
获取bug方法
jni层替换方法


修复补丁的具体过程是:
1)我们及时修复好bug之后,我们可以apkpatch工具将两个apk做一次对比,然后找出不同的部分。可以看到生成的apatch了文件。若果这个时候,我们把后缀改成zip再解压开,里面有一个dex文件。反编译之后查看一下源码,里面就是被修复的代码所在的类文件,这些更改过的类都加上了一个_CF的后缀,并且变动的方法都被加上了一个叫@MethodReplace的annotation,通过clazz和method指定了需要替换的方法。

2)客户端得到补丁文件后就会根据annotation来寻找需要替换的方法。从AndFixManager.fix方法开始,客户端找到对应的需要替换的方法,然后在fix方法的具体实现中调用fixClass方法进行方法替换过程。

3)由JNI层完成方法的替换。fixClass方法遍历补丁class里的方法,在jni层对所需要替换的方法进行一一替换。

private void replaceMethod(ClassLoader classLoader, String clz, String meth, Method method) {
	  try {
	    String key = clz + "@" + classLoader.toString();
	    Class<?> clazz = mFixedClass.get(key);
	    if (clazz == null) {// class not load
	      // 要被替换的class
	      Class<?> clzz = classLoader.loadClass(clz);
	      // 这里也很黑科技,通过C层,改写accessFlags,把需要替换的类的所有方法(Field)改成了public,具体可以看Method结构体
	      clazz = AndFix.initTargetClass(clzz);
	    }
	    if (clazz != null) {// initialize class OK
	      mFixedClass.put(key, clazz);
	      // 需要被替换的函数
	      Method src = clazz.getDeclaredMethod(meth, method.getParameterTypes());
	      // 这里是调用了jni,art和dalvik分别执行不同的替换逻辑,在cpp进行实现
	      AndFix.addReplaceMethod(src, method);
	    }
	  } catch (Exception e) {
	    Log.e(TAG, "replaceMethod", e);
	  }
	}

优点
1)可以多次打补丁。如果本地保存了多个补丁,那么AndFix会按照补丁生成的时间顺序加载补丁。具体是根据.apatch文件中的PATCH.MF的字段Created-Time。
2)安全性
readme提示开发者需要验证下载过来的apatch文件的签名是否就是在使用apkpatch工具时使用的签名,如果不验证那么任何人都可以制作自己的apatch文件来对你的APP进行修改。 但是我看到AndFix已经做了验证,如果补丁文件的证书和当前apk的证书不是同一个的话,就不能加载补丁。 官网还有一条,提示需要验证optimize file的指纹,应该是为了防止有人替换掉本地保存的补丁文件,所以要验证MD5码,然而SecurityChecker类里面也已经做了这个工作。。但是这个MD5码是保存在sharedpreference里面,如果手机已经root那么还是可以被访问的。
3)不需要重启APP即可应用补丁。
缺点
1)不支持YunOS 2)无法添加新类和新的字段 3)需要使用加固前的apk制作补丁,但是补丁文件很容易被反编译,也就是修改过的类源码容易泄露 4)使用加固平台可能会使热补丁功能失效 5)无法添加类和字段

###ClassLoader
大致的流程是:在dx工具执行之前,将LoadBugClass.class文件呢,进行修改,再其构造中添加System.out.println(dodola.hackdex.AntilazyLoad.class),然后继续打包的流程。注意:AntilazyLoad.class这个类是独立在hack.dex中。
总结下,其实我们需要做的就是两件事:
1、动态改变BaseDexClassLoader对象间接引用的dexElements;
2、在app打包的时候,阻止相关类去打上CLASS_ISPREVERIFIED标志。所有与该类相关的类都需要进行动态注入,可进行修改,也是需要进行fix的对象。
…
参考博客

###各个热修复方案优缺点

1、Dexpost:

1)原理:在底层虚拟机运行时hoop方法;

2)缺点:适配方面存在一些问题,目前不支持android6.0,5,1;art运行时;

3)优点:无需重启就可以达到修复bug的目的;

2、AndFix:

1)原理:在Native层使用指针替换的方法替换bug方法,达到修复bug的目的;

2)缺点:

底层替换,稳定性方面可能需要实际检测;

不支持YunOS;

无法添加新类和新的字段;

需要使用加固前的apk制作补丁,但是补丁文件很容易被反编译,也就是修改过的类源码容易泄露;

使用加固平台可能会使热补丁功能失效;

无法添加类和字段;

3)优点:无需中期就可以达到修复bug的目的;

3、HotFix:

1)原理:通过替换类加载器中bugclass,达到修复bug的目的;

2)缺点:需要重新启动才可以修复bug;

3)优点:java运行层修复,稳定性较好;

4、Nuwa:

1)原理:通过替换类加载器中bugclass,达到修复bug的目的;

2)缺点:需要重新启动才可以修复bug;

3)优点:java运行层修复,稳定性较好;自动化热修复

5、DroidFix:

1)原理:通过替换类加载器中bugclass,达到修复bug的目的;

2)缺点:需要重新启动才可以修复bug;

3)优点:java运行层修复,稳定性较好;

6、dynamic-load-apk

1)缺点:不支持Service和BroadcastReceiver;迁移成本高,需要修改插件,插件app需要继承自proxyActivity

2)优点: 插件无需安装host即可吊起;支持R访问插件资源;插件支持Activity和FragmentActivity;基本无反射调用;插件安装后任可独立运行

7、Droid Plugin

1)缺点:无法使用自定义资源的通知;法注册一些特殊Intent Filter的组件(四大组件);对Native支持不好

2)优点:插件无需任何修改,可独立安装运行,也可以做插件运行;四大组件无需在Host程序注册;超强隔离性,不同插件运行在不同的进程中;资源完全隔离;实现进程管理,插件的空进程会被及时回收,占用内存低;插件的静态广播会被当作动态处理,如果插件没有运行,静态广播永远不会触发;API侵入性低

8、DynamicAPK

1)优点: 迁移成本低(无需做任何activity/fragment/resource的proxy实现)不使用代理来管理插件的activity/fragment的生命周期。修改后aapt会处理插件种的资源,R.java中的资源引用和普通Android工程没有区别,开发者可以保持原有的开发规范;

更加有利于并发开发;

提升编译速度;

提升启动速度。

2)缺点:

dex解压、dexopt、加载耗时较长,使用按需加载启动时间过长


###使用Tinker
请见我另一篇详细的tinker接入说明


Android热修复——深入剖析AndFix热修复及自己动手实现 前言 去年写过一篇热修复的文章,那时候刚开始接触,照猫画虎画的还算比较成功。但是那种修复需要重新启动APP,也就是在JAVA层实现的热修复。我们知道目前Android主流的修复还有在Native层实现修复的,就是在Native层替换方法,不用重新启动APP。今天写了个Demo,下面主要分享一下它的主要原理。 1、热修复 目前,热修复的原理主要有两种技术,一是不需要启动APP就能实现修复,在Nati... 阅读详情

相关推荐

Android热修复原理热修复框架对比和代码修复

在Android应用开发中,热修复技术被越来越多的开发者所使用,也出现了很多热修复框架,比如:AndFix、Tinker、Dexposed和Nuwa等等。如果只是会这些热修复框架的使用那意义并不大,我们还需要了解它们的原理,这样不管热修复框架如何变化,只要基本原理不变,我们就可以很快的掌握它们。这一个系列不会对某些热修复框架源码进行解析,而是讲解热修复框架的通用原理。

2401_84121615的博客 915

热修复介绍

热修复介绍 1.热修复简介 ​ 热修复说白了就是”打补丁”,比如你们公司上线一个app,用户反应有重大bug,需要紧急修复。如果按照通 常做法,那就是程序猿加班搞定bug,然后测试,重新打包并发布。这样带来的问题就是成本高,效率低。于是,热 修复就应运而生.一般通过事先设定的接口从网上下载无Bug的代码来替换有Bug的代码。这样就省事多了,用 户体验也好。 2.阿里热修复框架使用 并且支持arm与...

qq_30996881的博客 4667

浅谈Android热修复

前言: 很多时候测试完的产品上线后,突然发现一个小的bug。这时候考虑到用户体验、和时间成本,不能为了一点点bug而重新发布新版本。于是就有了热修复这个概念的产生!它可以在不发布版本的情况下修复出bug的代码。我们来一探究竟。 目前可能用的相对广泛的热修复框架有如下几个: https://github.com/dodola/HotFix https://github.com/jasonro

比较喜欢、笑的博客专栏 1万+

热修复原理

什么是热修复? 定义:在我们应用上线后出现bug需要及时修复时,不用再发新的安装包,只需要发布补丁包,在客户无感知下修复掉bug。 怎么进行热修复? 服务端:补丁包管理 用户端:执行热修复 开发端:生成补丁包 热修复需要解决的问题 补丁包是什么? 如何生成补丁包? 开启混淆后呢? 对比改动自动生成补丁包(gradle)? 什么时候执行热修复? 怎么执行热修复(使用补丁包)? Android版本兼容问题? 热补丁方案有很多,其中比较出名..

BonnySoul的博客 1312

Android开发之热修复

一、前言   任何程序都无法保证上线后不会出现紧急bug,选择的修复方式不同,其代价也大不相同。所谓热修复,是相对于正常的版本迭代修复而言的,它可以及时在应用内下载补丁更新程序逻辑,修复bug;而不需要等到下一个版本发布。举个简单的例子,假如有一行代码的逻辑写错了,并且已经编译出APK,安装到了用户的手机上,此时有两种处理方式: 等待下一个版本发布,其中修复了错误代码,即迭代修复 给用户推送补丁,及时修复错误代码,即热修复 下图对比两者区别: 从上图可以看出热修复相对于迭代修复有很大优势: ..

鸿蒙开发知识记录 1159

airodump-ng、aircrack-ng使用教程

wifi破解、airodump-ng、aircrack-ng脚本

ssmbyss的博客 2232

热修复——紧急修复的大杀器

热修复,万字剖析!在实习中,我有幸参与了一项关键的任务,即实现应用程序的热修复功能。通过这个项目,我学习并了解了热修复技术,并且亲身体验了其在移动应用开发中的重要性和实际应用。在本文中,我将分享我在实习期间学到的关于热修复的知识和经验。我会介绍热修复的概念、原理以及在 Android 应用开发中的实际应用。同时,我还会探讨一些常用的热修复框架,关注我,让我们一起讨论我在实践中遇到的一些挑战和解决方案。

wei的博客 2584

DSPF28335:从零到一,实战GPIO与外部中断的嵌入式系统交互设计

本文以德州仪器DSPF28335芯片为例,详细讲解了嵌入式系统中GPIO与外部中断(EXTI)的实战配置方法。通过一个完整的按键控制LED并触发ADC采样的项目,深入剖析了GPIO寄存器配置、三级中断机制(外设-PIE-CPU)以及中断服务函数编写的核心要点,帮助开发者掌握嵌入式交互设计的基石,并提供了关键的避坑指南与调试清单。

weixin_29169899的博客 115

Android 热修复

1.Android热修复 热修复,就是对线上版本的静默更新。当APP发布上线之后,如果出现了严重的bug,通常需要重新发版来修复,但是频繁地发版显然不是最佳解决方案,所以出现了热修复,在用户无感知的情况下修复线上bug,避免频繁地发版。 在开发端,通过Gradle插件生成补丁包,并上传到云端,客户端通过判断是否需要下载新的补丁包,并执行热修复。 目前主流的热修复框架有腾讯的Tinker,阿里的AndFix、Sophix,美团的Robust。他们采用的修复方式不同,比如native层hook Jav

zenmela2011的专栏 4977

QT使用高精度定时器

精度相对第二种方法高许多。

ljjjjjjjjjjj的博客 4097

OpenClaw插件配置错误修复完全指南

插件文件名是插件目录结构正确package.json配置正确OpenClaw的插件系统还在快速迭代,偶尔会遇到这种配置问题。看错误信息检查配置文件检查实际文件对比差异修复问题大部分问题都能解决。查看官方文档:https://openclaw.ai/docs提Issue:https://github.com/openclaw/openclaw/issues加入Discord社区求助快速修复命令汇总。

Maynor的博客 4092

什么是热修复?它的优缺点是什么?

热修复就是通过下发补丁包,让已安装的客户端动态更新,用户不用重新安装APP,就能够修复软件缺陷。

maniuT的博客 842

LLCC68芯片系统架构与LoRa驱动开发核心解析

LoRa射频收发器是低功耗广域物联网(LPWAN)的关键组件,其本质是集成了调制解调器、协议引擎、数据缓冲区与电源管理的专用SoC。理解其工作模式状态机(Sleep/Standby/TX/RX)与SPI主机接口时序规范,是实现稳定通信的基础。LLCC68通过寄存器映射与命令集双接口抽象硬件控制,支持LoRa扩频调制与FSK兼容模式,具备高链路预算(157 dB)和DC-DC/LDO动态电源切换能力。典型应用场景包括远距离传感器节点、智能表计与工业无线监测系统。本文深入剖析LLCC68的信号链路径、中断机制与

weixin_29859471的博客 281

Android 热修复其实很简单

android AndFix 热修复 动态加载

Dennis-Android的博客 2万+

在anaconda环境中使用conda命令安装cuda、cudnn、tensorflow(-gpu)、pytorch

文章目录在anaconda环境中使用conda命令安装cuda、cudnn、tensorflow(-gpu)、pytorch结论参考资料解释相关命令版本关系版本选择总结:实验 在anaconda环境中使用conda命令安装cuda、cudnn、tensorflow(-gpu)、pytorch 结论 使用conda虚拟环境 使用conda命令安装 最重要的是版本关系(python、cuda、cudnn、pytor或者tensorflow框架)的对应。 参考资料 tensorflow2.x安装 理清GPU、

纸上得来终觉浅,绝知此事要躬行! 3万+

YOLOv11改进 | 特殊场景检测篇 | 利用图像去雾网络UnfogNet改进yolov11图像雾天检测能力(全网独家首发改进)

本文给大家带来的改进机制是利用UnfogNet超轻量化图像去雾网络,我将该网络结合YOLOv11针对图像进行去雾检测(也适用于一些模糊场景),我将该网络结构和YOLOv11的网络进行结合同时该网络的结构的参数量非常的小,我们将其添加到模型里增加的计算量和参数量基本可以忽略不计这是非常难得的,因为其也算是一种图像增强算法,同时本文的内容不影响其它的模块改进可以作为工作量凑近大家的论文里,非常的适用,图像去雾检测为群友最近提出的需要的改进。欢迎大家订阅我的专栏一起学习YOLO!

Snu77的博客 1628

Android热修复技术总结

主要是介绍Tinker热修复框架和Tinker热修复集成和修复bug流程

maguifen2012的博客 2003

使用verilog设计实现QR分解

QR(正交三角)分解法是求一般矩阵全部特征值的最有效并广泛应用的方法,一般矩阵先经过正交相似变化成为Hessenberg矩阵,然后再应用QR方法求特征值和特征向量。 使用verilog对QR实现方法进行设计并进行功能仿真: 如下: 顶层模块代码: module TOP( H1R, H1I, H2R, H2I, H3R, H3I, H4R, H4I, clk, rst_n, Y1R, Y1I, Y2R, Y2I, X1R, X1I, X2R, X2I ); parameter width = 16; // I

QQ_778132974的博客 2150

Android——Android热修复简单实现

本章会写出可以让你直接运行的Dome(后面附带本章节的源码) 一步一步跟着来肯定会成功!!! 再此先祝你成功啦。 APP更新,请参考APP版本更新该章节 前言:热修复是什么? 在刚进入王者荣耀的时候有没有遇见过,检测更新....再下载更新包...再解压压缩包...最后就可以进入游戏了。 没错!王者荣耀在上线的时候难免会出现bug,王者荣耀这是在修复bug。要是王者.........

GSLS 3902

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

热修复框架Tinker的从0到集成之路

热修复框架Tinker的从0到集成之路 转载请标明出处: http://blog.youkuaiyun.com/lisdye2/article/details/52049857 本文出自:【Alex_MaHao的博客】 项目中的源码已经共享到github,有需要者请移步【Alex_MaHao的github】 2015年10月,QQ空间提出了热修复方案,一时间热修复风靡Android界,阿里

茅屋 6553

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

全面了解Android热修复技术

作者:赵裕, 腾讯移动客户端开发 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处。 原文链接:http://wetest.qq.com/lab/view/338.htmlWeTest 导读本文探讨了Android热修复技术的发展脉络,现状及其未来。热修复技术概述热修复技术在近年来飞速发展,尤其是在InstantRun方案推出之后,各种热修复技术竞相涌现。国内大部分成熟的主流AP...

wetest_tencent的博客 1734

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Android热修复实现及原理

今天我将围绕热修复实现原理以及常见的热修复方式来讲解热修复。如下图: #mermaid-svg-9DOgBI8Cs6Y6bRHs .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-9DOgBI8Cs6Y6bRHs .label text{fill:#333}#mermaid-svg-9DOgBI8Cs6Y6bRHs

hirezy 1万+
上一篇: 自定义View的绘制原理图解
下一篇: 论 studio 3.0 的使用体验
Checkiming
博客等级 码龄10年 38粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值