Android类加载器的学习总结

本文详细介绍了Android中的类加载器,包括BootstrapLoader、PathClassLoader、DexClassLoader和InMemoryDexClassLoader的工作原理和创建过程,以及DexPathList和DexFile在类查找中的作用。内容涵盖从Java到Android的类加载机制,并解析了DexClassLoader的构造和findClass方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.  Java中的类加载器

<>   BootstrpLoader:C++实现、加载指定的JDK核心类库(java.lang、java.util)、/jre/lib路径下的类库。

<>  ExtClassLoader:加载java的拓展类,/jre/lib/ext路径下的类库

<>   ApplicationClassLoader:加载当前程序的ClassPath目录下的类

<>   CutomClassLoader:自定义类加载器,实现findClass方法

 

2.  Android中的类加载器

<>   BootstrpLoader:系统启动时预加载常用类,用java实现的

<>   PathClassLoader:加载已经安装过的apk的dex文件(data/cache),/data/app/package下的apk文件、也可以加载vendor/lib和System/lib 下的nativeLibrary

<>   DexClassLoader:加载dex文件以及包含dex的压缩文件(apk和jar文件),动态加载

<>   InMemoryDexClassLoader:在Android 8.0后加入,加载内存中的dex文件

 

3.  PathClassLoader的创建

Zygote进程启动> fork自身创建子进程(SystemServer)>调用ZygoteInit的startSystemServer方法>ZygoteInit.handleSystemServerProcess() >在createPathClassLoader方法里调用PathClassLoaderFactory的CreateClassLoader >创建成功

 

4.  BootstrpLoader的创建

Zygote进程启动—> fork自身创建子线程(SystemServer)—>调用ZygoteInit的preLoad方法—>调用ZygoteInit的preloadClasses方法?创建成功—>加载预加载类

预加载类:

ContextImpl、contextWraper、Dialog、Fragment、ApplicationPackage、ContentResolve

 

5.  DexClassLoader

public class DexClassLoader extends BaseDexClassLoader {

    public DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) {

        super((String)null, (File)null, (String)null, (ClassLoader)null);

        throw new RuntimeException("Stub!");

   }

}

dexPath:指定要加载dex文件的路径;

optimizedDirectory:指定dex文件需要被写入的目录,一般是应用程序内部路径(不可以为null);

librarySearchPath:包含native库的目录列表(可能为null);

parent:父类加载器;

 

DexClassLoader继承于BaseDexClassLoader,主要实现由BaseDexClassLoader的findClass方法实现。

谷歌官方的说明:

(PathClassLoader)Provides a simple ClassLoader implementation that operates on a list of files and directories in the local file system, but does not attempt to load classes from the network. Android uses this class for its system class loader and for its application class loader(s).

(DexClassLoader)A class loader that loads classes from .jar and .apk files containing a classes.dex entry. This can be used to execute code not installed as part of an application.

 

6.  BaseDexClassLoader

1.  BaseDexClassLoader里创建了DexPathList

2.  BaseDexClassLoader的findClass里执行的是DexPathList.findClass方法

3.  DexPathList类的构造方法里会创建一个Element[]数组

4.  Element[]数组里放的是DexFile文件

5.  DexPathList类调用makeElements方法遍历该程序路径下的所有文件,筛选出dex文件,然后生成DexFile类型的文件。(Apk、Dex、Jar)

6.  然后将DexFlie类型文件和路径信息存储到Element数组里。

7.  最终DexPathList调用findClass方法,遍历Element数组(DexFile),DexFlie会调用内部方法loadClassBinaryName,在DexFile文件里查找拼接成Class字节码返回。

8.  DexFlie的loadClassBinaryName方法最终是调用一个Native方法,叫defineClassNative。

9.  获取到字节码后,ART的AOT或者DVM的JIT就会将字节码转成机器码。

 

 BaseDexClassLoader的构造方法:

public BaseDexClassLoader(String dexPath, File optimizedDirectory,

            String libraryPath, ClassLoader parent) {

        super(parent);

        this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);

}

DexPathList类的代码实现:

class DexPathList {

    private static final String DEX_SUFFIX = ".dex";

    private final ClassLoader definingContext;

    private final Element[] dexElements;

    // 本地库目录

    private final File[] nativeLibraryDirectories;

    public DexPathList(ClassLoader definingContext, String dexPath,

            String libraryPath, File optimizedDirectory) {

               this.definingContext = definingContext;

        ArrayList<IOException> suppressedExceptions = new ArrayList<IOException>();

        // 遍历该程序路径下的所有文件

        this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory,

                                          suppressedExceptions);

        if (suppressedExceptions.size() > 0) {

            this.dexElementsSuppressedExceptions =

               suppressedExceptions.toArray(new IOException[suppressedExceptions.size()]);

        } else {

           dexElementsSuppressedExceptions = null;

        }

        this.nativeLibraryDirectories = splitLibraryPath(libraryPath);

    }

}

Element的构造方法

// file文件,是否是目录,zip文件通常都是apk或jar文件,dexFile就是.dex文件

Element(File file, boolean isDirectory, File zip, DexFile dexFile)

 

 makeDexElements方法

// 所有从dexPath找到的文件

for (File file : files) {

 // 如果是文件夹,就直接将路径添加到Element中

 if (file.isDirectory()) {

    elements.add(new Element(file, true, null, null));

  } else if (file.isFile()){

   //如果是文件且文件名以.dex结束,直接从.dex文件生成DexFile对象

   dex = loadDexFile(file, optimizedDirectory);

  } else {

   // 从APK/JAR文件中读取dex文件

   dex = loadDexFile(file, optimizedDirectory);

 }

if ((zip != null) || (dex != null)) {

  elements.add(new Element(file, false, zip, dex));

}

}

 

DexPathList.findClass方法:

public Class findClass(String name, List<Throwable> 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;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值