声明:原创文章,转载请备注来源: https://shuwoom.com/?p=142

备注:本文的Android源码版版本都是基于Android4.4.3
为了更好地理解APK加壳加固原理,我们需要对APP的启动流程进行分析,同时,我们整理提炼几个关键的问题,解决了下面的几个问题,对APP的启动过程理解和后面实战APK加固都很有帮助。

  • APP启动的大概流程?
  • 该过程中涉及到的比较重要的类、函数,及其之间的关系?
  • 在哪里创建LoadedApk?
  • 在哪里创建类加载器?
  • 哪里加载dex文件
  • 在哪里创建Application对象?

3.1 Android系统启动流程

在讲APP启动过程之前,我们先快速的了解下Android系统的启动流程。Android底层是基于Linux内核的,跟大多数Linux内核系统一样,系统启动时,bootloader先启动加载内核和执行init进程。init进程是系统启动后运行在用户控件的首个进程,如下图所示,init进程的PPID为1。
init进程启动完系统所需的各种守护线程后,接着根据init.rc文件中的配置创建启动Zygote进程。Zygote进程是Android系统中一个相当重要的进程,所有运行应用程序的Dalvik虚拟机都是由Zygote进程创建的,Zygote本身也是一个虚拟机进程。我们可以看到下图中zygote的PPID为52,PPID为1,也就是父进程为init进程。其他一些应用程序,如phone、email、sms、calendar等PPID都是52,也就是他们的父进程都是同一个zygote进程。
Zygote进程会开启一个Socket接口来监听请求,然后通过复制自身快速提供Dalvik虚拟机实例来执行应用程序。在Android中,每一个应用程序都运行着一个Dalvik虚拟机实例,每个Dalvik虚拟机实例都是一个独立的进程空间,这样可以很好的确保应用程序运行的独立性和安全性。
同时,Zygote会启动一个系统服务System Server管理进程,该进程会启动Android所有系统核心服务,包括Activity Manager Service、Package Manager Service等service。到这里,系统就准备好启动第一个APP进程-Home进程,也就是我们常说的Launcher进程。
TODO:参考《Android Dalvik虚拟机结构及机制剖析》第一卷第六章

 

3.2 几个关键类的关系和用途

在开始分析APP启动流程之前,我们事先了解下述几个在启动过程中比较关键的类:

  • ActivityThread
  • Application
  • Instrumentation
  • LoadedApk
  • ApplicationLoaders

3.2.1 ActivityThread类

(1) 用途:

一个App启动时会创建一个ActivityThread,它管理着app进程中主线程的执行,其main方法作为app启动的入口。它根据Activity Manager发送的请求,对activities、broadcasts和其他操作进行调度、执行。

(2)关键的成员和方法:

public final class ActivityThread {
    //关键成员
	final ApplicationThread mAppThread = new ApplicationThread();
	final H mH = new H();
	Application mInitialApplication;
	private static ActivityThread sCurrentActivityThread;
	Instrumentation mInstrumentation;
	final ArrayMap<String, WeakReference<LoadedApk>> mPackages
	            = new ArrayMap<String, WeakReference<LoadedApk>>();
	…
	//关键方法
	public static void main(String[] args) { … }
	private void attach(boolean system) { … }
	public final void bindApplication(String processName,
                ApplicationInfo appInfo, List<ProviderInfo> providers,
                ComponentName instrumentationName, String profileFile,
                ParcelFileDescriptor profileFd, boolean autoStopProfiler,
                Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
                Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
                Bundle coreSettings) { .. }
	private void handleBindApplication(AppBindData data) {…}
	…
}

3.2.2 Application类

(1) 用途:

通过ActivityThread类的定义我们知道,ActivityThread是单例模式,而且是应用程序的主线程。其中,Application对象mInitialApplication是该类的成员。可见,应用程序中有且仅有一个Application组件,它是全局的单例的。而且Application对象的生命周期跟应用程序的生命周期一样长,从应用启动开始到应用退出结束。

Application跟Activity、Service一样,是Android系统的一个组件,当Android程序启动时会创建一个Application对象,用来存储系统的一些信息。默认情况下,系统会帮我们自动创建一个Application对象,我们也可以在AndroidManifest.xml中指定并创建自己的Application做一些全局初始化的工作。

(2) 关键的成员和方法:

public class Application extends ContextWrapper implements ComponentCallbacks2 {

    //关键成员
	public LoadedApk mLoadedApk;
	…
	//关键方法
	public void onCreate(){ … }
	protected void attachBaseContext(Context base) { ... }
	…
}

3.2.3 Instrumentation类

 

(1) 用途:

同样,通过上面ActivityThread类的源码,我们知道在ActivityThread静态单例模式类中,有一个Instrumentation实例成员mInstrumentation。可见,Instrumentation同样也是全局的单例的。

Instrumentation主要是用来监控系统和应用的交互,并为ActivityThread创建Activity、Application等组件。

(2) 关键的成员和方法:

public class Instrumentation {
	//关键成员
	private ActivityThread mThread = null;
	private Context mInstrContext;
	private Context mAppContext;
	…
	//关键方法
	public void callApplicationOnCreate(Application app){ … }
	public Application newApplication(ClassLoader cl, String className, Context context){ … }
	static public Application newApplication(Class<?> clazz, Context context){ … }
	…
}

3.2.4 LoadedApk类

(1)用途:
一个应用程序对应一个LoadedApk对象。它用来保存当前加载的APK包的各种信息,包括app安装路径、资源路径、用户数据保存路径、使用的类加载器、Application信息等。
(2)关键的成员和方法:

public final class LoadedApk {      
    //关键成员      
    private final ActivityThread mActivityThread;      
    private final ClassLoader mBaseClassLoader;      
    private ClassLoader mClassLoader;      
    private Application mApplication;     
     …      
    //关键方法      
    public Application makeApplication(boolean forceDefaultAppClass, 
    Instrumentation instrumentation){…}  …

}

3.2.5 ApplicationLoaders类

(1)用途:
获取当前应用程序的类加载器,通过LoadedApk类的getClassLoader方法获取。
(2)关键的成员和方法:

class ApplicationLoaders{      
    //关键成员
    private final ArrayMap<String, ClassLoader> mLoaders = 
                        new ArrayMap<String, ClassLoader>(); 
    private static final ApplicationLoaders gApplicationLoaders = 
                        new ApplicationLoaders();      …      
    //关键方法
    public static ApplicationLoaders getDefault() { … }      
    public ClassLoader getClassLoader(String zip, String libPath, 
        ClassLoader parent) { … }  …
}

 

3.3APP启动流程

 

 

这里,我们讲解最常见的一种触发启动方式—用户点击启动。
当用户点击桌面上一个APP图标时,这个APP的启动流程大致如下:
(1)点击APP图标,产生Click Event事件;
(2)Launcher程序接收到Click Event事件,调用startActivity(Intent),通过Binder IPC机制调用Activity Manager  Service的服务;
(3)Activity Manager Service会调用startProcessLocked方法来创建新的进程;
(4)startProcessLocked方法调用Process类的静态成员函数start来创建这个APP的进程,并指定APP进程的入口函数为android.app.ActivityThread类的静态成员函数main;
(5)main方法成功创建ActivityThread对象后,再调用attach方法完成初始化,然后进入消息循环,直到进程退出;
接下来,我们就通过源码一步步分析上述流程。

 

3.3.1 指定app的入口方法

我们从startProcessLocked方法开始分析,其关键代码如下:

 

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
	…
	private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) {
	    …
	    Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
	                    app.processName, uid, uid, gids, debugFlags, mountExternal,
	                    app.info.targetSdkVersion, app.info.seinfo, null);
	    …
	}
}

可以看到,startProcessLocked方法调用Process类的start方法创建应用程序的进程,并指定android.app.ActivityThread类的main方法为入口函数。
下面我们看ActivityThread类的main方法的定义:

public final class ActivityThread {   
    …      public static void main(String[] args) {         
    …          
    Looper.prepareMainLooper();          
    ActivityThread thread = new ActivityThread();          
    thread.attach(false);         
     …          
    Looper.loop();          
    …      }       …
}

main方法首先创建ActivityThread类对象,并调用attach方法完成初始化,然后调用Looper.loop()方法进入消息循环。这里我们看下attach()方法做了哪些初始化工作。

 

public final class ActivityThread {
   …
 private void attach(boolean system) {
         sCurrentActivityThread = this;
         mSystemThread = system;
         if (!system) {
             ViewRootImpl.addFirstDrawHandler(new Runnable() {
                 @Override
                 public void run() {
                     ensureJitEnabled();
                 }
             });
             android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                     UserHandle.myUserId());
             RuntimeInit.setApplicationObject(mAppThread.asBinder());
             IActivityManager mgr = ActivityManagerNative.getDefault();
             try {
                 mgr.attachApplication(mAppThread);
             } catch (RemoteException ex) {
                 // Ignore
             }
         }
 …
 } 
 …
}

通过上面thread.attach(false)函数调用,我们知道这里传递过来的参数是false,也就是非系统应用。ActivityManagerNative.getDefault()获取的是ActivityManagerService实例,这里,ActivityManagerService对象通过attachApplication绑定ApplicationThread对象mAppThread。这里,我们观察下ApplicationThread类。
ApplicationThread是ActivityThread的内部类,其定义如下:

public final class ActivityThread {
    …      private class ApplicationThread extends ApplicationThreadNative{ … }      …
}

 

ApplicationThread继承了ApplicationThreadNative抽象类,再看下ApplicationThreadNative的定义:

 

public abstract class ApplicationThreadNative extends Binder implements IApplicationThread {
    …
}

 

而ApplicationThreadNative抽象类继承了Binder类并实现了IApplicationThread接口。
所以,传递给attach参数的是ApplicationThread类型的Binder对象,它主要的作用是用来进行进程间的通信。
下面进入ActivityManagerService,查看attachApplication方法:

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {      …      public final void attachApplication(IApplicationThread thread) {          
    synchronized (this) {              
        int callingPid = Binder.getCallingPid();              
        final long origId = Binder.clearCallingIdentity();              
        attachApplicationLocked(thread, callingPid);              
        Binder.restoreCallingIdentity(origId);         
        }      
    }      …
}

attachApplication调用attachApplicationLocked方法,继续分析:

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {      
    …      
    private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {      
    //创建app对象      
    ProcessRecord app;          
    if (pid != MY_PID && pid >= 0) {              
        synchronized (mPidsSelfLocked) {                  
            app = mPidsSelfLocked.get(pid);              
        }              
    } else {              
        app = null;          
    }     
     …      
    //优化odex文件      
    ensurePackageDexOpt(app.instrumentationInfo != null =? app.instrumentationInfo.packageName                      : 
app.info.packageName);     
     …      
    thread.bindApplication(processName, appInfo, providers,                      
    app.instrumentationClass, profileFile, profileFd, profileAutoStop,                      
    app.instrumentationArguments, app.instrumentationWatcher,                      
    app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,                      isRestrictedBackupMode || !normalMode, app.persistent,                      new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),                      
    mCoreSettingsObserver.getCoreSettingsLocked());              
    updateLruProcessLocked(app, false, null);      
    …      
    //启动Activity     
    if (normalMode) {              
    try {                  
        if (mStackSupervisor.attachApplicationLocked(app, mHeadless)) {                      
        didSomething = true;                  
        }              
    } catch (Exception e) {                  
        badApp = true;              
    }          
    }          
    //启动Service     
     if (!badApp) {             
         try {                  
            didSomething |= mServices.attachApplicationLocked(app, processName);              
        } catch (Exception e) {                  
            badApp = true;              
        }          
    }      
    …      }      …
}

TODO:新加了内容
通过上面分析,我们知道,传递过来的thread对象是ApplicationThread类型的Binder对象,通过该Binder对象,跨进程调用ActivityThread的bindApplication方法,下面我们回到ActivityThread类。

public final class ActivityThread {
    …
    public final void bindApplication(String processName,
                ApplicationInfo appInfo, List<ProviderInfo> providers,
                ComponentName instrumentationName, String profileFile,
                ParcelFileDescriptor profileFd, boolean autoStopProfiler,
                Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
                Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
                Bundle coreSettings) {
        …
        AppBindData data = new AppBindData();
        data.processName = processName;
        data.appInfo = appInfo;
        data.providers = providers;
        data.instrumentationName = instrumentationName;
        data.instrumentationArgs = instrumentationArgs;
        data.instrumentationWatcher = instrumentationWatcher;
        data.instrumentationUiAutomationConnection = instrumentationUiConnection;
        data.debugMode = debugMode;
        data.enableOpenGlTrace = enableOpenGlTrace;
        data.restrictedBackupMode = isRestrictedBackupMode;
        data.persistent = persistent;
        data.config = config;
        data.compatInfo = compatInfo;
        data.initProfileFile = profileFile;
        data.initProfileFd = profileFd;
        data.initAutoStopProfiler = false;
        queueOrSendMessage(H.BIND_APPLICATION, data);  }  …
}

3.3.2 发送BIND_APPLICATION消息并处理

bindApplication方法调用queueOrSendMessage函数发送H.BIND_APPLICATION消息和data数据。queueOrSendMessage方法定义如下:

public final class ActivityThread {
    …      private void queueOrSendMessage(int what, Object obj) {          
        queueOrSendMessage(what, obj, 0, 0);      
    }      
    private void queueOrSendMessage(int what, Object obj, int arg1) {          
        queueOrSendMessage(what, obj, arg1, 0);     
    }      
    private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {          
        synchronized (this) {              
        …              
        Message msg = Message.obtain();              
        msg.what = what;              
        msg.obj = obj;              
        msg.arg1 = arg1;              
        msg.arg2 = arg2;              
        mH.sendMessage(msg);          
    }      }      …
}

 

queueOrSendMessage最终调用queueOrSendMessage(int what, Object obj, int arg1, int arg2)方法,并调用mH对象发送消息,这里msg.what = H.BIND_APPLICATION。我们调到ActivityThread的内部类H:

 

public final class ActivityThread {
…
private class H extends Handler {
    public static final int LAUNCH_ACTIVITY         = 100;
    public static final int PAUSE_ACTIVITY          = 101;
    public static final int PAUSE_ACTIVITY_FINISHING= 102;
    public static final int STOP_ACTIVITY_SHOW      = 103;
    public static final int STOP_ACTIVITY_HIDE      = 104;
    public static final int SHOW_WINDOW             = 105;
    public static final int HIDE_WINDOW             = 106;
    public static final int RESUME_ACTIVITY         = 107;
    public static final int SEND_RESULT             = 108;
    public static final int DESTROY_ACTIVITY        = 109;
    public static final int BIND_APPLICATION        = 110;
    …
    public void handleMessage(Message msg) {      
       switch (msg.what) {           
       case LAUNCH_ACTIVITY : {…} break;           
       case RELAUNCH_ACTIVITY : {…} break;           
         …           
       case BIND_APPLICATION:
           Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
            AppBindData data = (AppBindData)msg.obj; 
            handleBindApplication(data);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 
            break;                 
            … 
        }
    }
     …      
    } 
     …
}

    我们可以看到,H对象接收并处理各种消息,包括启动、暂停、关闭各个组件等操作。

上面,我们知道mH发送的是BIND_APPLICATION的消息,mH对象收到消息后,调用handleBindApplication对象处理传递过来的data对象数据。这个是app启动过程中最关键的方法。在这个方法里,有几个比较重要的操作跟加固相关:

  • 创建LoadedApk对象
  • 获取类加载器加载apk
  • 创建Application对象

我们看下handleBindApplication方法具体做了些什么。

public final class ActivityThread {
…
private void handleBindApplication(AppBindData data) {
    mBoundApplication = data;
    …
    //创建LoadedApk对象
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    …
    final ContextImpl appContext = new ContextImpl();
    appContext.init(data.info, null, this);
    …
    //创建Application对象          
    Application app = data.info.makeApplication(data.restrictedBackupMode, null);          
    mInitialApplication = app;
    …
    //启动app
    mInstrumentation.callApplicationOnCreate(app);     
    …
    }
    …
}

3.3.3 创建LoadedApk对象

handleBindApplication方法首先通过getPackageInfoNoCheck函数创建,而getPackageInfoNoCheck内部又调用getPackageInfo完成实际的LoadedApk创建工作。

public final class ActivityThread {
    …
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
            CompatibilityInfo compatInfo) {
        return getPackageInfo(ai, compatInfo, null, false, true);
}
…
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
            ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
    synchronized (mResourcesManager) {
        WeakReference<LoadedApk> ref;
        if (includeCode) {
            ref = mPackages.get(aInfo.packageName);
        } else {
            ref = mResourcePackages.get(aInfo.packageName);
        }
        LoadedApk packageInfo = ref != null ? ref.get() : null;
        if (packageInfo == null || (packageInfo.mResources != null
                && !packageInfo.mResources.getAssets().isUpToDate())) {
            …
            //创建LoadedApk对象
            packageInfo = new LoadedApk(this, aInfo, compatInfo, this, baseLoader,
                        securityViolation, includeCode &&
                        (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
            if (includeCode) {
                //添加到mPackages列表中
                mPackages.put(aInfo.packageName,
                        new WeakReference<LoadedApk>(packageInfo));
            } else {
                mResourcePackages.put(aInfo.packageName,
                        new WeakReference<LoadedApk>(packageInfo));
            }
        }
        return packageInfo;
    }
}
…
}

这里,由于LoadedApk是第一次创建,所以ref为空,需要创建LoadedApk对象并添加到mPackages列表中。最后,通过getPackageInfoNoCheck方法,返回LoadedApk对象。我们接着看data.info.makeApplication方法。这里data.info就是getPackageInfoNoCheck返回的LoadedApk对象。

public final class LoadedApk {
    …
    public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Application app = null;
        //Application类的完整包名
        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            //获取类加载器
            java.lang.ClassLoader cl = getClassLoader();
            ContextImpl appContext = new ContextImpl();
            appContext.init(this, null, mActivityThread);
            //创建Application对象
            app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            …
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
        …
        return app;
    }…
}

3.3.4 创建PathClassLoader加载dex

makeApplication调用getClassLoader给应用程序创建类加载器.

public final class LoadedApk{
    public ClassLoader getClassLoader() {
        synchronized (this) {
            if (mClassLoader != null) {
                return mClassLoader;
            }
            //第三方应用程序
            if (mIncludeCode && !mPackageName.equals("android")) {
                String zip = mAppDir;
                String libraryPath = mLibDir;
                
                String instrumentationAppDir = mActivityThread.mInstrumentationAppDir;
                String instrumentationAppLibraryDir = mActivityThread.mInstrumentationAppLibraryDir;
                String instrumentationAppPackage = mActivityThread.mInstrumentationAppPackage;
                String instrumentedAppDir = mActivityThread.mInstrumentedAppDir;
                String instrumentedAppLibraryDir = mActivityThread.mInstrumentedAppLibraryDir;
                String[] instrumentationLibs = null;

                if (mAppDir.equals(instrumentationAppDir)
                        || mAppDir.equals(instrumentedAppDir)) {
                    zip = instrumentationAppDir + ":" + instrumentedAppDir;
                    libraryPath = instrumentationAppLibraryDir + ":" + instrumentedAppLibraryDir;
                    if (! instrumentedAppDir.equals(instrumentationAppDir)) {
                        instrumentationLibs =
                            getLibrariesFor(instrumentationAppPackage);
                    }
                }

                if ((mSharedLibraries != null) || (instrumentationLibs != null)) {
                    zip = combineLibs(mSharedLibraries, instrumentationLibs) + ':' + zip;
                }
                …
                mClassLoader = ApplicationLoaders.getDefault().getClassLoader(
                        zip, libraryPath, mBaseClassLoader);
                …
            } else {
                //系统应用程序
                if (mBaseClassLoader == null) {
                    mClassLoader = ClassLoader.getSystemClassLoader();
                } else {
                    mClassLoader = mBaseClassLoader;
                }
            }
            return mClassLoader;
        }
    }
}

这里,由于我们是第一次调用getClassLoader方法,所以,mClassLoader为null。同时,我们的包名是属于第三方应用的包,且mIncludeCode为true。此时进入第一个if条件。所以,这里,调用ApplicationLoaders.getDefault().getClassLoader获取。我们看下ApplicationLoaders下的getClassLoader方法:

 

class ApplicationLoaders{
public ClassLoader getClassLoader(String zip, String libPath, ClassLoader parent){
        //父类加载器为BootClassLoader
        ClassLoader baseParent = ClassLoader.getSystemClassLoader().getParent();

        synchronized (mLoaders) {
            if (parent == null) {
                parent = baseParent;
            }
           
            if (parent == baseParent) {
                ClassLoader loader = mLoaders.get(zip);
                if (loader != null) {
                    return loader;
                }
               …
                PathClassLoader pathClassloader = new PathClassLoader(zip, libPath, parent);
                …
                mLoaders.put(zip, pathClassloader);
                return pathClassloader;
            }
            …
            PathClassLoader pathClassloader = new PathClassLoader(zip, parent);
            …
            return pathClassloader;
        }
    }
}

也就是说,当parent 为null时,设置parent为BootClassLoader,即设置父类加载器为BootClassLoader。否则,当parent==baseParent,如果mLoaders列表中已存在该类的类加载器,则返回,否则就调用下面的代码创建一个给该apk创建新的PathClassLoader加载器,并将app的目录名和对应的类加载器添加到mLoaders列表中。

PathClassLoader pathClassloader = new PathClassLoader(zip, libPath, parent);

我们知道Android加载Dex文件有两个方法,分别是DexClassLoader和PathClassLoader类加载器。
两者的区别是,DexClassLoader可以加载外部的Dex文件,而PathClassLoader只能加载已经安装了的apk的dex文件。到这里,我们就知道,dex文件的加载解析工作就发生在PathClassLoader类加载其中。我们会在第五章“Dalvik加载和解析dex过程”详细分析这一过程。
我们可以创建一个Android工程验证一下上面的结论:

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.v("loader", getClassLoader().toString());
        Log.v("loader", getClassLoader().getParent().toString());
    }
}

可以看到输出日志为:

也就是说应用程序的类加载器是PathClassLoader类型,其父加载器是BootClassLoader,跟我们上面分析的一样。
通过这一节内容,我们就知道了解了Android应用程序的类加载器的来源和流程,以及应用程序的类是如加载进来的。

3.3.5 创建Application对象

我们接着回到makeApplication方法中,当获取到应用程序的类加载器后,接着就是调用mActivityThread.mInstrumentation.newApplication方法创建Application对象。也就是说,实际的Application创建工作时交给Instrumentation对象完成。

public class Instrumentation {
    …
    public Application newApplication(ClassLoader cl, String className, Context context)
        throws InstantiationException, 
        IllegalAccessException, 
        ClassNotFoundException {
            return newApplication(cl.loadClass(className), context);
        }
    static public Application newApplication(Class<?> clazz, Context context)
        throws InstantiationException, 
        IllegalAccessException, 
        ClassNotFoundException {
        Application app = (Application)clazz.newInstance(); 
        app.attach(context);
        return app;
    }     …
}

 

newApplication用我们上一步获取的类加载器PathClassLoader来加载Application类(没有指明Application,则加载系统默认的Appli类,否则加载自定义的的Application类),并调用另一个版本的newApplication。
在该方法中,通过上一步加载获取的字节码创建Application类的实例对象,并调用attach方法绑定context,到这里我们就完成了Application类对象的创建。

3.3.6 启动Activity

完成Application对象的创建后,我们回到ActivityManagerService类中的attachApplicationLocked方法中。最后,程序通过调用mStackSupervisor类对象的attachApplicationLocked方法启动Activity。
位置:Android源码/framework/base/services/java/com/android/server/am/ActivityStackSupervisor.java

boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
    boolean didSomething = false;
    final String processName = app.processName;
    for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
        final ActivityStack stack = mStacks.get(stackNdx);
        if (!isFrontStack(stack)) {
            continue;
        }
        ActivityRecord hr = stack.topRunningActivityLocked(null);
        if (hr != null) {
            if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                    && processName.equals(hr.processName)) {
                try {
                    if (headless) {
                        …
                    } else if (realStartActivityLocked(hr, app, true, true)) {
                        didSomething = true;
                    }
                } catch (Exception e) {
                    …
                }
            }
        }
    }
    if (!didSomething) {
        ensureActivitiesVisibleLocked(null, 0);
    }
    return didSomething;
}

这里调用了realStartActivityLocked方法:

位置:Android源码/framework/base/services/java/com/android/server/am/ActivityStackSupervisor.java

 

final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)throws RemoteException {
    r.startFreezingScreenLocked(app, 0);
    if (false) Slog.d(TAG, "realStartActivity: setting app visibility true");
mWindowManager.setAppVisibility(r.appToken, true);
…
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    new Configuration(mService.mConfiguration), r.compat,
                    app.repProcState, r.icicle, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profileFile, profileFd,
                    profileAutoStop);
…

}

 

TODO:补充说明
app.thread调用schedulelaunchActivity方法通过Binder机制进入到ApplicationThread类的schedulelaunchActivity方法。
位置:Android源码\frameworks\base\core\java\android\app\ActivityThread.java

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
                int procState, Bundle state, List<ResultInfo> pendingResults,
                List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
                String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
    updateProcessState(procState, false);

    ActivityClientRecord r = new ActivityClientRecord();
    …
    queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}

 

这里跟3.3.2一样调用queueOrSendMessage方法发送LAUNCH_ACTIVITY的消息。我们回到handleMessage方法怎么处理。

 

public void handleMessage(Message msg) {      
    switch (msg.what) {
    case LAUNCH_ACTIVITY: {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = (ActivityClientRecord)msg.obj;              
        r.packageInfo = getPackageInfoNoCheck(
        r.activityInfo.applicationInfo, r.compatInfo);
        handleLaunchActivity(r, null);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     } break;
    … 
    }
    }
    …
}

这里最终调用了handleLaunchActivity方法完成Activity的启动。

 

 

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {  …  Activity a = performLaunchActivity(r, customIntent);      …      handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed);
    …
}

handleLaunchActivity方法调用performLaunchActivity创建Activity对象并调用OnCreate方法。完成对象创建后,调用handleResumeActivity调用OnResume方法,跟Activity生命周期一致,如下图。

 

我们进入performLaunchActivity方法:

 

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
   …
   Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            …
        }
   …
   mInstrumentation.callActivityOnCreate(activity, r.state);
   …
}

可以最终创建Activity的是Instrumentation类对象,它调用newActivity方法创建并返回Activity对象。
在创建完Activity对象后,调用callActivityOnCreate方法启动Activity。到此完成了Activity的启动。
我们看下newActivity方法做了些什么。
位置:

public Activity newActivity(ClassLoader cl, String className,Intent intent)
            throws InstantiationException, IllegalAccessException,ClassNotFoundException {
    return (Activity)cl.loadClass(className).newInstance();
}

我们看到newActivity方法是通过调用类加载器加载具体的类的。关于Dalvik加载类方法的过程我们会在第六章详细讲解。

 

参考

[1]Android系统源代码情景分析》第12Android应用程序进程的启动过程。罗升阳著。.

[2] [Android Application启动流程分析http://www.jianshu.com/p/a5532ecc8377

[3] Android应用的启动过程分析(强烈推荐) http://www.jianshu.com/p/a1f40b39b3de

[4] Android Context是什么?http://blog.csdn.net/feiduclear_up/article/details/47356289

[5] Android ActivityThread(主线程或UI线程)简介 http://blog.csdn.net/myarrow/article/details/14223493

[6] Android Application介绍 http://www.ctolib.com/topics/73986.html

[7] App’s ClassLoader的来源 http://whataa.github.io/2016/10/31/App’s%20ClassLoader%E7%9A%84%E6%9D%A5%E6%BA%90/

[8] Android中Hook Instrumentation的一些思考 http://blog.csdn.net/shifuhetudi/article/details/52078445

[9]【Android源码-AMS】(一)Instrumentation类解析 http://blog.csdn.net/nemo__/article/details/50528249

[10] Android应用程序启动过程源代码分析 http://blog.csdn.net/luoshengyang/article/details/6689748

[11] Android应用程序进程启动过程的源代码分析http://blog.csdn.net/luoshengyang/article/details/6747696

[12] Android Application启动流程分析 http://www.jianshu.com/p/a5532ecc8377

[13]《Android Dalvik虚拟机结构及机制剖析》-第一卷 第六章Dalvik虚拟机执行流程详解

 

打赏

发表评论

电子邮件地址不会被公开。