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);
    // 1、创建Context
    ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
    // 2、获取类加载器
    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
精品内容独家发布平台


呈现与博客不一样的技术干货

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值