天天看點

Android應用的ClassLoader建立過程

還是從Application的建立說起

/frameworks/base/core/java/android/app/ActivityThread.java
private void handleBindApplication(AppBindData data) {
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), false, true, false);
    // 、建立Context
    ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
    // 、擷取類加載器
    java.lang.ClassLoader cl = instrContext.getClassLoader();
    mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
    Application app = data.info.makeApplication(data.restrictedBackupMode, null);
    mInitialApplication = app;
    mInstrumentation.callApplicationOnCreate(app);
}
           

1、建立Context

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
    if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
    // 直接建立一個ContextImpl對象
    return new ContextImpl(null, mainThread,
            packageInfo, null, null, false, null, null);
}
           
/frameworks/base/core/java/android/app/ContextImpl.java
private ContextImpl(ContextImpl container, ActivityThread mainThread,
        LoadedApk packageInfo, IBinder activityToken, UserHandle user, boolean restricted,
        Display display, Configuration overrideConfiguration) {
    mOuterContext = this;

    mMainThread = mainThread;
    mActivityToken = activityToken;
    mRestricted = restricted;

    if (user == null) {
        user = Process.myUserHandle();
    }
    mUser = user;
    // ContextImpl的mPackageInfo存放有對應的LoadedApk對象
    mPackageInfo = packageInfo;
    mResourcesManager = ResourcesManager.getInstance();
    mDisplay = display;
    mOverrideConfiguration = overrideConfiguration;

    final int displayId = getDisplayId();
    CompatibilityInfo compatInfo = null;
    if (container != null) {
        compatInfo = container.getDisplayAdjustments(displayId).getCompatibilityInfo();
    }
    if (compatInfo == null && displayId == Display.DEFAULT_DISPLAY) {
        compatInfo = packageInfo.getCompatibilityInfo();
    }
    mDisplayAdjustments.setCompatibilityInfo(compatInfo);
    mDisplayAdjustments.setActivityToken(activityToken);
    Resources resources = packageInfo.getResources(mainThread);
    if (resources != null) {
        if (activityToken != null
                || displayId != Display.DEFAULT_DISPLAY
                || overrideConfiguration != null
                || (compatInfo != null && compatInfo.applicationScale
                        != resources.getCompatibilityInfo().applicationScale)) {
            resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),
                    packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),
                    packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,
                    overrideConfiguration, compatInfo, activityToken);
        }
    }
    mResources = resources;

    if (container != null) {
        mBasePackageName = container.mBasePackageName;
        mOpPackageName = container.mOpPackageName;
    } else {
        mBasePackageName = packageInfo.mPackageName;
        ApplicationInfo ainfo = packageInfo.getApplicationInfo();
        if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) {
            // Special case: system components allow themselves to be loaded in to other
            // processes.  For purposes of app ops, we must then consider the context as
            // belonging to the package of this process, not the system itself, otherwise
            // the package+uid verifications in app ops will fail.
            mOpPackageName = ActivityThread.currentPackageName();
        } else {
            mOpPackageName = mBasePackageName;
        }
    }

    mContentResolver = new ApplicationContentResolver(this, mainThread, user);
}
           

2、擷取類加載器

/frameworks/base/core/java/android/app/ContextImpl.java
@Override
    public ClassLoader getClassLoader() {
    // 前面說過mPackageInfo存放有對應的LoadedApk對象
        return mPackageInfo != null ?
                mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
    }
           
/frameworks/base/core/java/android/app/LoadedApk.java
public ClassLoader getClassLoader() {
    synchronized (this) {
        if (mClassLoader != null) {
            return mClassLoader;
        }
        // 調用ApplicationLoaders的getClassLoader方法
        mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, lib,
                    mBaseClassLoader);

        return mClassLoader;
    }
}
           
/frameworks/base/core/java/android/app/ApplicationLoaders.java
public ClassLoader getClassLoader(String zip, String libPath, ClassLoader parent)
{
    ClassLoader baseParent = ClassLoader.getSystemClassLoader().getParent();

    synchronized (mLoaders) {
        if (parent == null) {
            parent = baseParent;
        // ClassLoader會被緩存在mLoaders中,也就是說它也是隻會建立一次
        if (parent == baseParent) {
            ClassLoader loader = mLoaders.get(zip);
            if (loader != null) {
                return loader;
            }
            // 如果緩存中沒有,就會建立一個PathClassLoader來對應用進行加載
            PathClassLoader pathClassloader =
                new PathClassLoader(zip, libPath, parent);
            mLoaders.put(zip, pathClassloader);
            return pathClassloader;
        }
        return pathClassloader;
    }
}
           
歡迎關注微信公衆号:DroidMind 精品内容獨家釋出平台
Android應用的ClassLoader建立過程
呈現與部落格不一樣的技術幹貨

繼續閱讀