从Activity的启动初探类的加载流程

1.入口

 protected void startActivity(Class clazz) {
        Intent intent = new Intent(this,clazz);
        startActivity(intent);
    }

2. 调用startActivityForResult

  @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

3. 执行execStartActivity

  public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
      ...
        Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
      ...

  }

4. 构建代理管理类

   public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
      ...
      //构建manager代理类
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
      ...
}

5.使用binder调用底层管理类

   private static final Singleton gDefault = new Singleton() {
        protected IActivityManager create() {
            //!!!
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

然后的然后...

6.回到ActivityThread的performLaunchActivity()方法

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  ...
     java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
      //核心代码!!!
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
  ...

  }

7.创建类的实例

    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }
    protected Class loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
            // First, check if the class has already been loaded
            Class c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                ...
                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    //最终执行
                    c = findClass(name);
                }
            }
            return c;
    }

Classload通过类名找到相应的.class文件,然后通过反射创建出类的实例

8.寻找findClass源码

查看源码发现,Classload并没有实现findClass方法,此外通过之前传入的cl对象发现存在这样的继承关系关系:
Classload→BaseDexClassLoader→PathClassLoader

9.查找findClass的具体实现代码

网址:http://androidxref.com/
找到BaseDexClassLoader

   @Override
          protected Class findClass(String name) throws ClassNotFoundException {
                   List suppressedExceptions = new ArrayList();
          //核心代码!!!
                 Class c = pathList.findClass(name, suppressedExceptions);
                  if (c == null) {
                          ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);
                           for (Throwable t : suppressedExceptions) {
                                cnfe.addSuppressed(t);
                             }
                          throw cnfe;
                     }
                  return c;
              }
  public BaseDexClassLoader(String dexPath, File optimizedDirectory,
                String libraryPath, ClassLoader parent) {
            super(parent);
            this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
        }

原理:通过名字在一个DexPathList集合中找到相应的.class文件

    public Class findClass(String name, List suppressed) {
                    for (Element element : dexElements) {
                            DexFile dex = element.dexFile;
                
                            if (dex != null) {
                                    Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
                                    if (clazz != null) {
                                            return clazz;
                                        }
                                }
                        }
                    if (dexElementsSuppressedExceptions != null) {
                            suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
                        }
                    return null;
                }

dex文件由Element数组管理,通过遍历dexElements,然后通过传入的class名字就可以找到相应的class文件

10.写在最后

此文仅作为学习笔记

你可能感兴趣的:(从Activity的启动初探类的加载流程)