Tencent Shadow

2020-03-01 3577浏览

  • 1.主题:Tencent Shadow 如何在成熟的Android插件技术领域继续创新? 郭琨 前腾讯⾼高级⼯工程师
  • 2.个⼈人介绍 郭琨 • 前腾讯⾼高级⼯工程师 • 平安科技安卓技术专家 • Shadow插件框架作者之⼀一
  • 3.内容⼤大纲 01 插件框架是做什什么的? 02 为什什么说插件框架是个成熟的领域了了? 03 Shadow在这个领域做出了了哪些创新? 04 Shadow核⼼心技术原理理
  • 4.插件框架是什什么? 没⽤用插件框架时
  • 5.插件框架是做什什么的? ⽤用了了插件框架时
  • 6.插件框架是做什什么的? • 减少安装包体积 • 动态发布新功能 • 动态修复线上bug • ⾃自解耦业务 ………… 插件框架的其他⽤用途
  • 7.为什什么说插件框架是个成熟的领域? 框架名称 开发者 推出时间 AndroidDynamicLoader ⼤大众点评 2012年年6⽉月 Atlas 阿⾥里里 2013年年中 DL(Dynamic_Load_apk) 任⽟玉刚 OpenAltas(ACCD) bunnyblue 2014年年1⽉月 2015年年8⽉月 DroidPlugin 2015年年8⽉月 DynamicAPK 360 携程 Small 林林⼴广亮 2016年年6⽉月 VirtualAPK 滴滴 2017年年6⽉月 RePlugin 2017年年7⽉月 Phantom 360 满帮集团 Tencent Shadow 腾讯 2019年年6⽉月 插件框架发展时间线 2015年年11⽉月 2018年年10⽉月
  • 8.为什什么说插件框架是个成熟的领域? 360发布RePlugin
  • 9.Shadow做出了了哪些创新? • 零反射、⽆无Hack实现插件框架 • 全动态插件框架
  • 10.Shadow做出了了哪些创新? 插件框架——公认的⿊黑科技
  • 11.Shadow做出了了哪些创新? Android 9.0 限制私有API调⽤用
  • 12.Shadow做出了了哪些创新? Github上第⼀一个号称零Hook的插件框架
  • 13.Shadow做出了了哪些创新? W/.phantom.sampl:Accessing hidden method Landroid/view/ View;->computeFitSystemWindows(Landroid/graphics/ Rect;Landroid/graphics/Rect;)Z (light greylist, reflection) W/System.err:StrictMode VmPolicy violation with POLICY_DEATH; shutting down. I/Process:Sending signal.PID:15302SIG:9 Application terminated. 严格模式下运⾏行行Phantom的Sample
  • 14.Shadow做出了了哪些创新? 反射调⽤用插件Activity的⽣生命周期⽅方法 反射复制Activity的私有域 零Hook不不等于零反射
  • 15.Shadow做出了了哪些创新? 插件core组件 插件manager组件 插件container组件 动态加 载 插件 插件loader组件 插件框架 宿主 通⽤用的插件框架架构
  • 16.Shadow做出了了哪些创新? 业务需要新功能 修改次数 13% 兼容不不同⼿手机系统 87% 插件框架本身也有更更新需求
  • 17.Shadow做出了了哪些创新? 插件core组件 动态 加载 插件Manager组件 动态 加载 插件loader组件 插件container组件 宿主 全动态插件架构 动态 加载 插件
  • 18.Shadow做出了了哪些创新? 对宿主增量量对⽐比 3000 增量量 2250 1500 750 0 RePlugin Atlas QQ PluginSdk Phantom 全动态架构对宿主增量量极⼩小 Shadow
  • 19.Shadow核⼼心技术原理理 那么我们是如何实现这些创新呢?
  • 20.Shadow核⼼心技术原理理 其他框架: Shadow: 系统 安装的App宿主 系统 安装的App宿主 ⾮非法访问 插件 Shadow中间层 插件 Shadow基本原理理
  • 21.Shadow核⼼心技术原理理 插件Activity正常运⾏行行2 个条件:系统⽅方法调⽤用成功 ⽣生命周期⽅方法正确回调 ⽅法调⽤ 插件 Activity Android 系统 ⽣命周期⽅法 回调
  • 22.Shadow核⼼心技术原理理 系统Activity 系统Activity 继承 继承 代理理 Activity 插件 Activity 宿主 插件 代理理模式开发插件Activity的基本原理理
  • 23.Shadow核⼼心技术原理理 系统Activity 系统Activity 继承 继承 代理理 Activity 系统⽅方法调⽤用 插件基类 Activity 继承 插件 Activity 常规代理理模式系统⽅方法调⽤用 系统⽅方法调⽤用
  • 24.Shadow核⼼心技术原理理 系统Activity 继承 代理理 Activity 系统⽅方法调⽤用 Shadow Activity 系统⽅方法调⽤用 继承 插件 Activity Shadow中的插件Activity⽅方法调⽤用
  • 25.Shadow核⼼心技术原理理 常规代理理模式⽣生命周期⽅方法回调
  • 26.Shadow核⼼心技术原理理 常规代理理模式⽅方法回调有执⾏行行顺序问题
  • 27.Shadow核⼼心技术原理理 Shadow采⽤用组合解决
  • 28.Shadow核⼼心技术原理理 系统Activity 继承 插件 Activity 正常APP开发 Shadow Activity(普通 类) 继承 插件 Activity Shadow插件开发 代理理模式有代码侵⼊入性问题
  • 29.Shadow核⼼心技术原理理 代理理模式对开发插件带来了了代码侵⼊入性,同时⽆无法处理理jar包中activity 源码/jar .class Activity 动态编译 (transform) JavaAssist dex ShadowActivity Shadow对代码侵⼊入性的解决⽅方案
  • 30.Shadow核⼼心技术原理理 AOP——⾯面向切⾯面编程 插件开发就是不不断寻找合适的切⾯面
  • 31.Shadow核⼼心技术原理理 插件Activity的intent,系统⽆无法识别,需要转换为对应壳⼦子Activity的intent PendingIntent .getActivity(context, requestCode, intent, flags, options); ShadowPendingIntent .getActivity(context, requestCode, intent, flags, options); ⼤大部分切⾯面都能通过Javassist轻松修改
  • 32.Shadow核⼼心技术原理理 getPackageManager() -> PackageManager getPackageManager() -> ProxyPackageManager 常规插件框架对PackageManager的处理理
  • 33.Shadow核⼼心技术原理理 PackageManager @Override getApplicationInfo() @hide abstract hideMethod() 继承 ProxyPackageManager @Override getApplicationInfo() 继承的⽅方式需要兼容hide及⼚厂商添加⽅方法
  • 34.Shadow核⼼心技术原理理 packageManager.getApplicationInfo(String packageName,int flag) ShadowPackageManager.getApplicationInfo(packageManager,packageName,flag) 期望的⽅方法转调处理理
  • 35.Shadow核⼼心技术原理理 Javassist没有对应⽀支持的⾼高级API
  • 36.Shadow核⼼心技术原理理 Class A { public D add(B b, C c) { } } 1. aload_0 2. bipush 12 3. bipush 13 4. invokevirtual #A.add(B,C) 5. ireturn Class S { public static D add(A a, B b, C c) { } } 1. aload_0 2. bipush 12 3. bipush 13 4. invokestatic #S.add(A,B,C) 5. ireturn 分析2种⽅方法的调⽤用区别
  • 37.Shadow核⼼心技术原理理 ⾮非常⼩小的改动达到了了⽬目的
  • 38.Shadow核⼼心技术原理理 全动态插件架构有什什么创新点?
  • 39.Shadow核⼼心技术原理理 加载系统类 BootClassLoader 双亲委派 BootClassLoader parent parent 加载安装的 app类 PathClasLoader parent PathClasLoader PluginClasLoader parent ⽆无法复⽤用宿主的类 加载插件中 的类 PluginClasLoader 存在类冲突问题 传统的ClassLoader类加载有局限性
  • 40.Shadow核⼼心技术原理理 loadclass(name) 否 从⾃自⼰己的类路路径中搜 索 是 抛出异常 找不不到? 包名是否在 ⽩白名单中 否 是 是 委托给parent 找不不到? 正常返回 定制ClassLoader⽀支持⽩白名单访问 否
  • 41.Shadow核⼼心技术原理理 BootClassLoader parent PathClasLoader 正常访问 ⽩白名单访 问 parent PluginClasLoader 定制插件ClassLoader类访问说明
  • 42.Shadow核⼼心技术原理理 插件core组件 宿主 动态 加载 插件Manager模块 动态 加载 插件loader组件 动态 加载 插件container组件 代理理Activity及运⾏行行时需要 的类 回顾⼀一下全动态插件架构 插件
  • 43.Shadow核⼼心技术原理理 系统启动Activity时,总是从PathClassLoader去查找 BootClassLoader parent PathClasLoader ? parent ContainerClasLo ader 传统的ClassLoader双亲委派是否可以打破?
  • 44.Shadow核⼼心技术原理理 public abstract class ClassLoader { private final ClassLoader parent; 反射私有变量量parent就能改变原有双亲委 派结构 //....... } 阅读源码寻找双亲委派的逻辑
  • 45.Shadow核⼼心技术原理理 BootClassLoader parent parent x ContainerClasLo ader ● 修改安全 ● ⾮非插件框架必须点 PathClasLoader parent 打破ClassLoader的双亲委派
  • 46.Shadow核⼼心技术原理理 优化RePlugin的核⼼心技术
  • 47.Shadow核⼼心技术原理理 Boot ClassLoader parent Path ClassLoader 访问读写PathClassLoader私有域 复制内容, 替换 访问读写PackageInfo私有域 Boot ClassLoader parent RePlugin ClassLoader RePlugin ClassLoader parent Plugin ClassLoader RePlugin唯⼀一的Hook点实现
  • 48.Shadow核⼼心技术原理理 Boot ClassLoader parent RePlugin ClassLoader parent PathClassLoa der parent Plugin ClassLoader ⽆无限制API调⽤用实现Replugin核⼼心hook
  • 49.总结 • 基础知识⾮非常重要,总能在关键问题上起决定性作⽤用 • 任何软件⼯工程领域的问题,都可以通过增加⼀一个中间层来解决 • 不不建议使⽤用反射,只有在⾯面向未来编程时才是正确的解决⽅方案
  • 50.开源 Shadow GitHub开源地址:https://github.com/Tencent/Shadow欢迎star,issue,pr
  • 51.Thank you for your attention! 郭琨