[实践] Android5.1.1源码 - 让某个APP以解释执行模式运行

简介:

前言


本文的实践修改了Android5.1.1的源码。

本文只简单的讲了一下原理。在“实践”一节讲了具体做法。


本文的内容涉及Art模式下dex加载的知识,想要详细了解这部分知识可以去看老罗的文章: 

Android运行时ART简要介绍和学习计划 

Android运行时ART加载OAT文件的过程分析 

Android运行时ART加载类和方法的过程分析 

Android运行时ART执行类方法的过程分析


本文的内容涉及zygote,如果不知道zygote是什么,或者好奇zygote如何启动,可以去看老罗的文章: 
Android系统进程Zygote启动过程的源代码分析


老罗的文章分析的是Android2.3的源码,所以下面提到的与zygote有关的函数在老罗的文章里面可能没有,如果想要对下面提到的与zygote有关的函数有一个简单的了解可以看我的文章:Android5.1.1源码 - zygote fork出的子进程如何权限降级


原理简介


怎么才能让方法解释执行


在函数ClassLinker::LinkCode中会链接dex中的方法代码,这个函数的定义在文件”art/runtime/class_linker.cc”中,下面是它的源码(这里只列出了与本文有关的部分):


在这个函数中调用了NeedsInterpreter函数判断当前方法是否要解释执行,如果返回值为true,即局部变量enter_interpreter被赋值为true,那么调用ArtMethod类中的SetEntryPointFromQuickCompiledCode函数并将GetQuickToInterpreterBridge()的返回值传入,GetQuickToInterpreterBridge()函数返回用于解释执行的函数的入口地址,这个入口函数解释执行dex中的方法。


那么现在来看看NeedsInterpreter函数,这个函数的定义在文件”art/runtime/class_linker.cc”中,下面是它的源码:



当”Runtime::Current()->GetInstrumentation()->InterpretOnly()”返回true且不是本地方法和代理方法,那么这个函数就会返回true,否则返回false。


InterpretOnly函数是Instrumentation类的成员函数,它的函数定义在文件”art/runtime/instrumentation.h”中,下面是它的源码:



interpret_only_是类Instrumentation的成员变量,是布尔类型。可以发现InterpretOnly函数仅仅是将”interpret_only_”返回,如果将interpret_only_设置为true,那么根据上文分析,所有“非本地且非代理”方法都将被解释执行。


那么如何将interpret_only_设置为true哪,在Instrumentation类中有一个ForceInterpretOnly函数,下面是这个函数的源码:



这个函数是Instrumentation类的公有成员函数,所以直接调用这个函数即可将interpret_only_设置为true。


这里有一个问题,将interpret_only_设置为true,那么“非本地且非代理”方法在链接代码时都将被设置成解释执行,那么会不会影响到其他的APP进程?不会,因为ClassLinker::LinkCode函数对方法的链接是在APP进程的内存中进行的,所以这个操作并不会影响到其他进程。

这里进行一个小节,当执行”Runtime::Current()->GetInstrumentation()->ForceInterpretOnly()”语句时,会把Instrumentation对象的interpret_only_成员变量设置为true。那么当方法是“非本地且非代理”方法时,NeedsInterpreter函数将返回true,那么在ClassLinker::LinkCode函数中会将这个方法设置为解释执行。

如果要将APP中所有方法都设置为解释执行,那么就需要在链接APP的dex中的方法代码之前执行”Runtime::Current()->GetInstrumentation()->ForceInterpretOnly()”语句。




调用ForceInterpretOnly函数的时机


我的办法是在EnableDebugFeatures函数中调用ForceInterpretOnly函数,在这一节中会先说明Android如何执行到EnableDebugFeatures函数,然后会说明在EnableDebugFeatures函数中调用ForceInterpretOnly函数的好处。

所有的Android应用进程都是zygote fork出来的,fork APP进程时的函数调用路径:



调用完ForkAndSpecializeCommon函数后APP进程就被fork出来了。


ForkAndSpecializeCommon函数定义在文件”frameworks/base/core/jni/com_android_internal_os_Zygote.cpp”中,下面它的源码:


gCallPostForkChildHooks是一个全局变量,它在com_android_internal_os_Zygote.cpp文件的register_com_android_internal_os_Zygote函数中被初始化。


env->CallStaticVoidMethod(…)语句调用了Java方法”Zygote.callPostForkChildHooks”。


下面是Zygote.callPostForkChildHooks方法的源码,这个方法在文件”frameworks/base/core/java/com/android/internal/os/Zygote.java”中:



VM_HOOKS是Zygote类的成员变量,下面是它的定义:




VM_HOOKS.postForkChild调用的就是ZygoteHooks类中的成员方法postForkChild,这个方法在文件”libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java”中,下面是它的源码:




这个方法中调用了native函数nativePostForkChild,nativePostForkChild函数的C层代码在文件”/home/sowuy/android/system/art/runtime/native/dalvik_system_ZygoteHooks.cc”中,下面是它的源码:



我将在EnableDebugFeatures函数中调用ForceInterpretOnly函数,原因有三点:

  1. EnableDebugFeatures函数参数接收的是一个标志,我可以设置一个新的标志位用来表示是否需要调用ForceInterpretOnly函数。
  2. 每次APP启动的时候都会执行EnableDebugFeatures函数。
  3. EnableDebugFeatures函数被调用的时机好,它运行在fork出的APP进程中,并且在链接APP的dex中的方法前被调用。




实践



修改Zygote.java中的代码


Zygote.java文件的位置是:frameworks/base/core/java/com/android/internal/os/Zygote.java,在Zygote类中添加一个成员变量:


在Zygote类forkAndSpecialize方法的开始部分添加下面的代码:


修改dalvik_system_ZygoteHooks.cc中的代码


dalvik_system_ZygoteHooks.cc文件的位置是:art/runtime/native/dalvik_system_ZygoteHooks.cc,修改这个文件中的EnableDebugFeatures函数的代码。

向这个函数中添加下面的代码:


下面是对这个函数修改后的完整代码:

相关文章
|
22天前
|
XML Java Android开发
Android实现自定义进度条(源码+解析)
Android实现自定义进度条(源码+解析)
51 1
|
22天前
|
Java Android开发
Android反编译查看源码
Android反编译查看源码
23 0
|
1月前
|
调度 数据库 Android开发
构建高效Android应用:Kotlin协程的实践与优化
在Android开发领域,Kotlin以其简洁的语法和平台友好性成为了开发的首选语言。其中,Kotlin协程作为处理异步任务的强大工具,它通过提供轻量级的线程管理机制,使得开发者能够在不阻塞主线程的情况下执行后台任务,从而提升应用性能和用户体验。本文将深入探讨Kotlin协程的核心概念,并通过实例演示如何在实际的Android应用中有效地使用协程进行网络请求、数据库操作以及UI的流畅更新。同时,我们还将讨论协程的调试技巧和常见问题的解决方法,以帮助开发者避免常见的陷阱,构建更加健壮和高效的Android应用。
36 4
|
1月前
|
移动开发 监控 安全
mPaaS常见问题之Android集成dexPatch热修复运行时候无法正常进行热更新如何解决
mPaaS(移动平台即服务,Mobile Platform as a Service)是阿里巴巴集团提供的一套移动开发解决方案,它包含了一系列移动开发、测试、监控和运营的工具和服务。以下是mPaaS常见问题的汇总,旨在帮助开发者和企业用户解决在使用mPaaS产品过程中遇到的各种挑战
34 0
|
1月前
|
移动开发 Java Android开发
构建高效Android应用:Kotlin协程的实践之路
【2月更文挑战第31天】 在移动开发领域,性能优化和流畅的用户体验一直是开发者追求的目标。随着Kotlin语言的流行,其异步编程解决方案——协程(Coroutines),为Android应用带来了革命性的并发处理能力。本文将深入探讨Kotlin协程的核心概念、设计原理以及在Android应用中的实际应用案例,旨在帮助开发者掌握这一强大的工具,从而提升应用的性能和响应能力。
|
1月前
|
移动开发 调度 Android开发
构建高效Android应用:探究Kotlin协程的优势与实践
【2月更文挑战第30天】 在移动开发领域,尤其是针对Android平台,性能优化和应用流畅度始终是开发者关注的重点。近年来,Kotlin语言凭借其简洁性和功能性成为Android开发的热门选择。其中,Kotlin协程作为一种轻量级的线程管理解决方案,为异步编程提供了强大支持,使得编写非阻塞性代码变得更加容易。本文将深入分析Kotlin协程的核心优势,并通过实际案例展示如何有效利用协程提升Android应用的性能和响应速度。
|
23天前
|
Java Android开发 开发者
构建高效Android应用:Kotlin协程的实践与优化
在响应式编程范式日益盛行的今天,Kotlin协程作为一种轻量级的线程管理解决方案,为Android开发带来了性能和效率的双重提升。本文旨在探讨Kotlin协程的核心概念、实践方法及其在Android应用中的优化策略,帮助开发者构建更加流畅和高效的应用程序。通过深入分析协程的原理与应用场景,结合实际案例,本文将指导读者如何优雅地解决异步任务处理,避免阻塞UI线程,从而优化用户体验。
|
1天前
|
Linux 开发工具 Android开发
Docker系列(1)安装Linux系统编译Android源码
Docker系列(1)安装Linux系统编译Android源码
3 0
|
2天前
|
测试技术 Android开发
Android App获取不到pkgInfo信息问题原因
Android App获取不到pkgInfo信息问题原因
12 0
|
2天前
|
JSON 编译器 开发工具
VS Code阅读Android源码
VS Code阅读Android源码
9 1