Java_ClassLoader(ClassLoader / 自定义ClassLoader / DexClassLoader)

本文详细介绍了Java的ClassLoader原理,包括双亲委托模型,以及在Android中的具体运用。重点讲解了如何自定义ClassLoader,并对比了DexClassLoader和PathClassLoader在加载.dex文件时的区别和应用场景。示例代码展示了如何使用这两种ClassLoader加载和调用插件中的类和资源。

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

Java_ClassLoader(ClassLoader / 自定义ClassLoader / DexClassLoader)


本文由 Luzhuo 编写,转发请保留该信息.
原文: http://blog.youkuaiyun.com/rozol/article/details/77758194


ClassLoader 用来动态加载class文件到内存中使用的
ClassLoader 使用 双亲委托模型 来搜索类的
ClassLoader 在Android中有两个子类来加载.dex文件, 分别是 DexClassLoader / PathClassLoader
DexClassLoader 可以加载 jar / apk(未安装/已安装) / dex
PathClassLoader 只可以加载 系统中已安装的apk

原理

/**
 * ClassLoader
 * ClassLoader用来动态加载class文件到内存中使用的;
 * JVM并不会一次性加载程序的所有class文件, 而是根据所需加载.
 * 
 * 
 * Java内置的ClassLoader
 * BootStrap ClassLoader 启动类加载器 (c++编写, 嵌于JVM内核), 负责加载jdk的核心库类 (@Code = printBootStrapClassPath())
 * Extension ClassLoader 扩展类加载器 (Java编写, 继承于ClassLoader), 负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目下的所有jar (@Code = printExtensionClassPath())
 * App ClassLoader 应用程序(系统)类加载器 (Java编写, 继承于ClassLoader), 负责加载应用程序classpath目录下的所有jar和class文件 (@Code = printAppClassPath())
 * 
 * 
 * ClassLoader原理 (@Code = classLoaderMod())
 * 使用 `双亲委托模型` 来搜索类
 * 每个ClassLoader都有一个父类加载器的引用, 如下所示, BootStrap ClassLoader 没有父类加载器, 可作为其他ClassLoader的父类加载器
 * 
 *  启动类加载器 (BootStrap ClassLoader)
 *      ↑
 *  扩展类加载器 (Extension ClassLoader)
 *      ↑
 *  应用程序(系统)类加载器 (App ClassLoader)
 *      ↑
 *  自定义类加载器 (<? extend ClassLoader>)
 * 
 * 当ClassLoader需要加载某个类时, 从 BootStrap ClassLoader 开始检索, 如果没有找到则从Extension ClassLoader 检索, 同理依次传递, 如果都没有, 则麻烦委托者自己从文件或网络检索, 还是没有则抛 ClassNotFoundException 异常.
 * 如果某个类加载器找到该类文件, 则将其生成类的定义, 加载到内存当中, 返回实例对象.
 * 如果该类已经存在缓存中, 类加载器将不再去检索, 而是将缓存中的类返回.
 * 
 * 该模式的好处: 从上到下依次检索, 避免了 恶意代码冒充系统类代码 安全隐患;
 * 因为类加载器只要从自家的类加载中检索到所需的系统代码, 就不会执行用户写的类加载器, 从而避免被调包
 * 
 * 
 * 判断两个类是否相同?
 * 如果两个类的 全类名 相同, 且被同一个类加载器加载的, 即为同一个class;
 * 如果两个类的 全类名 相同, 但被非同一个类加载器加载的, 即为非同一个class.
 * 
 * @author Luzhuo
 */
public class Test{
    public static void main(String[] args) throws ClassNotFoundException, Exception {
        // 输出 BootStrap ClassLoader 加载的文件路径
        printBootStrapClassPath();

        // 输出 Extension ClassLoader 加载的文件路径
        printExtensionClassPath();

        // 输出 App ClassLoader 加载的文件路径
        printAppClassPath();



        // 双亲委托模型
        classLoaderMod();
    }

    /**
     * 输出BootStrap ClassLoader 加载的文件路径
     */
    private static void printBootStrapClassPath(){
        // 方式1: 源码中的文件
        final String bootClassPath = System.getProperty("sun.boot.class.path");
        System.out.println("BootStrap ClassLoader - path: " + bootClassPath);

        // 方式2: 类提供的方法
        URL[] urls = Launcher.getBootstrapClassPath().getURLs();
        for (int i = 0; i < urls.length; i++) {
            System.out.println(urls[i].toExternalForm()); 
        }
    }

    /**
     * 输出 Extension ClassLoader 加载的文件路径
     */
    private static void printExtensionClassPath(){
        final String extensionClassPath = System.getProperty("java.ext.dirs");
        System.out.println("Extension ClassLoader - path: " + extensionClassPath);
    }

    /**
     * 输出 App ClassLoader 加载的文件路径
     */
    private static void printAppClassPath(){
        final String appClassPath = System.getProperty("java.class.path");
        System.out.println("App ClassLoader - path: " + appClassPath);
    }


    /**
     * 双亲委托模型
     * ClassLoader原理 (Code = classLoaderMod())
     */
    private static void classLoaderMod(){
        ClassLoader loader = Test.class.getClassLoader(); 
        while(loader != null) {  
            System.out.println("classLoaderMod: " + loader);
            loader = loader.getParent(); // 获取父类加载器  
        }

        // classLoaderMod: sun.misc.Launcher$AppClassLoader@73d16e93
        // classLoaderMod: sun.misc.Launcher$ExtClassLoader@15db9742
        // BootStrap ClassLoader 为C++所写, 故未打印
    }
}

源码

双亲委托模型
public abstract class ClassLoader {
    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            // ↓↓↓
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                 try {
                    if (parent != null) {
                        // ↓↓↓
                        c = parent.loadClass(name, false);
                    } else {
                        // ↓↓↓
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值