Android ClassLoader机制

什么是ClassLoader?

Classloader动态的装载Class文件。标准的java sdk中有一个ClassLoader类,借助这个类可以装载想要的Class文件,每个ClassLoader对象在初始化时必须制定Class文件的路径。
写程序的时候不是有import关键字可以引用制定的类吗?为何还要使用这个类加载器呢?
原因其实是这样的,使用import关键字引用的类必须符合以下两个条件
1. 类文件必须在本地,当程序运行时需要次类时,这时类装载器会自动装载该类,程序员不需要关注此过程。
2. 编译的时候必须有这个类文件,否则编译不通过。
想让程序在运行的时候动态调用怎么办呢?用import显示是不符合上面的两种要求的。此时ClassLoader就派上用场了。

Android DexClassLoader

android应用程序,本质上使用的是java开发,使用标准的java编译器编译出Class文件,和普通的java开发不同的地方是把class文件再重新打包成dex类型的文件,这种重新打包会对Class文件内部的各种函数表、变量表等进行优化,最终产生了odex文件。odex文件是一种经过android打包工具优化后的Class文件,因此加载这样特殊的Class文件就需要特殊的类装载器,所以android中提供了DexClassLoader类

public DexClassLoader (String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent)

Added in API level 3
Creates a DexClassLoader that finds interpreted and native code. Interpreted classes are found in a set of DEX files contained in Jar or APK files.
创建一个DexClassLoader用来找出指定的类和本地代码(c/c++代码)。用来解释执行在DEX文件中的class文件。

Parameters

  1. dexPath 需要装载的APK或者Jar文件的路径。包含多个路径用File.pathSeparator间隔开,在Android上默认是 “:”
  2. optimizedDirectory 优化后的dex文件存放目录,不能为null
  3. libraryPath 目标类中使用的C/C++库so文件的路径,每个目录用File.pathSeparator间隔开; 可以为null
  4. parent 该类装载器的父装载器,一般用当前执行类的装载器

类装载器DexClassLoader的具体使用
这个类的使用过程基本是这样:
1. 传递apk/jar目录,dex的解压缩目录,c/c++库的目录
2. 创建一个 DexClassLoader实例
3. 加载指定的类返回一个Class
4. 然后使用反射调用这个Class

Android ClassLoader机制

ClassLoader

Android使用的是Dalvik虚拟机装载class文件,所以classloader不同于java默认类库rt.jar包中java.lang.ClassLoader, 可以看到android中的classloader做了些修改,但是原理还是差不多的,实现了双亲委托模型

public abstract class ClassLoader {
    static private class SystemClassLoader {
        public static ClassLoader loader = ClassLoader.createSystemClassLoader();
    }
    private ClassLoader parent;

    private static ClassLoader createSystemClassLoader() {
        String classPath = System.getProperty("java.class.path", "."); //adb shell中执行getprop java.class.path命令查看,此时发现没有值
        return new PathClassLoader(classPath, BootClassLoader.getInstance()); //getSystemClassLoader加载器是pathclassloader,它的parent是BootClassLoader,但是DexPathList[[directory "."]..
    }

    public static ClassLoader getSystemClassLoader() {
        return SystemClassLoader.loader; //返回系统默认类加载器
    }

    ClassLoader(ClassLoader parentLoader, boolean nullAllowed) {
        if (parentLoader == null && !nullAllowed) {
            throw new NullPointerException("parentLoader == null && !nullAllowed");
        }
        parent = parentLoader;
    }
    //自定义classloader需要重载该方法
    protected Class<?> findClass(String className) throws ClassNotFoundException {
        throw new ClassNotFoundException(className);
    }
    protected final Class<?> findLoadedClass(String className) {
        ClassLoader loader;
        if (this == BootClassLoader.getInstance()) //如果该classloader是BootClassLoader类型
            loader = null;
        else
            loader = this;
        return VMClassLoader.findLoadedClass(loader, className); //调用本地c/c++方法
    }
    //可以看到android系统其实也实现了双亲委托模型,只是跟java的双亲委托模型有点不同而已,虚拟机不同嘛
    protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
        Class<?> clazz = findLoadedClass(className); //检查是否已经加载过
        if (clazz == null) {
            ClassNotFoundException suppressed = null;
            try {
                clazz = parent.loadClass(className, false); //使用parent去查找
            } catch (ClassNotFoundException e) {
                suppressed = e;
            }

            if (clazz == null) {
                try {
                    clazz = findClass(className); //调用findclass
                } catch (ClassNotFoundException e) {
                    e.addSuppressed(suppressed);
                    throw e;
                }
            }
        }
        return clazz;
    }
    //可以看到loadClass的resolve参数是没用的
    protected final void resolveClass(Class<?> clazz) {
    }
}
//BootClassLoader单例模型
class BootClassLoader extends ClassLoader {
    private static BootClassLoader instance;
    @FindBugsSuppressWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED")
    public static synchronized BootClassLoader getInstance() {
        if (instance == null) {
            instance = new BootClassLoader();
        }
        return instance;
    }
    public BootClassLoader() {
        super(null, true);
    }
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        return Class.classForName(name, false, null);
    }
}

BaseDexClassLoader

PathClassLoader和DexClassLoader的基类,重载了findClass方法,直接交给DexPathList处理

BaseDexClassLoader类分析

public class BaseDexClassLoader extends ClassLoader {
    /** originally specified path (just used for {@code toString()}) */
    private final String originalPath;
    /** structured lists of path elements */
    private final DexPathList pathList;

    public BaseDexClassLoader(String dexPath, File optimizedDirectory,
            String libraryPath, ClassLoader parent) {
        super(parent);
        this.originalPath = dexPath;
        this.pathList =
            new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
    }
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class clazz = pathList.findClass(name); //实际上是通过DexPathList来查找类的
        if (clazz == null) {
            throw new ClassNotFoundException(name);
        }
        return clazz;
    }
    @Override
    protected URL findResource(String name) {
        return pathList.findResource(name);
    }
    @Override
    protected Enumeration<URL> findResources(String name) {
        return pathList.findResources(name);
    }
    @Override
    public String findLibrary(String name) {
        return pathList.findLibrary(name);
    }
    @Override
    protected synchronized Package getPackage(String name) {
        if (name != null && !name.isEmpty()) {
            Package pack = super.getPackage(name);
            if (pack == null) {
                pack = definePackage(name, "Unknown", "0.0", "Unknown",
                        "Unknown", "0.0", "Unknown", null);
            }
            return pack;
        }
        return null;
    }
    @Override
    public String toString() {
        return getClass().getName() + "[" + originalPath + "]";
    }
}

DexClassLoader和PathClassLoader类

都继承自BaseDexClassLoader,只是有不同的构造函数,唯一的区别PathClassLoader就是optimizedDirectory参数为null,很好理解嘛,PathClassLoader加载的是data/app/…安装目录下的dex,但是
DexClassLoader加载外部未安装的dex/apk/jar/zip等,所以需要把最后的odex文件放在optimizedDirectory目录,所以不能为null

public class DexClassLoader extends BaseDexClassLoader {
    public DexClassLoader(String dexPath, String optimizedDirectory,
            String libraryPath, ClassLoader parent) {
        super(dexPath, new File(optimizedDirectory), libraryPath, parent);
    }
}

public class PathClassLoader extends BaseDexClassLoader {
    public PathClassLoader(String dexPath, ClassLoader parent) { //PathClassLoader
        super(dexPath, null, null, parent);
    }
    public PathClassLoader(String dexPath, String libraryPath,
            ClassLoader parent) {
        super(dexPath, null, libraryPath, parent);
    }
}

DexPathList类分析

/*package*/ final class DexPathList {
    //支持的文件格式
    private static final String DEX_SUFFIX = ".dex";
    private static final String JAR_SUFFIX = ".jar";
    private static final String ZIP_SUFFIX = ".zip";
    private static final String APK_SUFFIX = ".apk";
    /** class definition context */
    private final ClassLoader definingContext; //持有的classloader引用
    /** list of dex/resource (class path) elements */
    private final Element[] dexElements; //elements集合
    /** list of native library directory elements */
    private final File[] nativeLibraryDirectories; //本地库so文件目录

    public DexPathList(ClassLoader definingContext, String dexPath,
            String libraryPath, File optimizedDirectory) {
        ......
        this.definingContext = definingContext;
        this.dexElements =
            makeDexElements(splitDexPath(dexPath), optimizedDirectory); //调用makeDexElements方法,splitDexPath(dexPath)方法返回dexPath路径下所有files的集合
        this.nativeLibraryDirectories = splitLibraryPath(libraryPath);
    }
    //返回Element[]数组,每个Element就是一个jar,dex,apk,zip文件,如果是这几种文件格式那么就会被添加到dexElements中去了
    private static Element[] makeDexElements(ArrayList<File> files,
            File optimizedDirectory) {
        ArrayList<Element> elements = new ArrayList<Element>();
        for (File file : files) {
            ZipFile zip = null;
            DexFile dex = null;
            String name = file.getName();
            if (name.endsWith(DEX_SUFFIX)) { //如果是dex后缀名
                // Raw dex file (not inside a zip/jar).
                try {
                    dex = loadDexFile(file, optimizedDirectory); //调用loadDexFile方法返回dex
                } catch (IOException ex) {
                    System.logE("Unable to load dex file: " + file, ex);
                }
            } else if (name.endsWith(APK_SUFFIX) || name.endsWith(JAR_SUFFIX)
                    || name.endsWith(ZIP_SUFFIX)) { //如果是apk,jar,zip后缀名
                try {
                    zip = new ZipFile(file);
                } catch (IOException ex) {
                    System.logE("Unable to open zip file: " + file, ex);
                }
                try {
                    dex = loadDexFile(file, optimizedDirectory); //调用loadDexFile方法返回dex
                } catch (IOException ignored) {
                }
            } else {
                System.logW("Unknown file type for: " + file);
            }
            if ((zip != null) || (dex != null)) {
                elements.add(new Element(file, zip, dex)); //添加一个Element,注意这里的参数,file,zip,dex
            }
        }
        return elements.toArray(new Element[elements.size()]);
    }
    private static DexFile loadDexFile(File file, File optimizedDirectory)
            throws IOException {
        if (optimizedDirectory == null) {
            return new DexFile(file);
        } else {
            String optimizedPath = optimizedPathFor(file, optimizedDirectory);
            return DexFile.loadDex(file.getPath(), optimizedPath, 0); //实际调用的是DexFile的loadDex静态方法
        }
    }
    //关键方法,查找类会对循环对所有的dex文件进行查找,知道找到第一个符合条件的停止
    public Class findClass(String name) {
        for (Element element : dexElements) {
            DexFile dex = element.dexFile;
            if (dex != null) {
                Class clazz = dex.loadClassBinaryName(name, definingContext); //实际调用的是DexFile的loadClassBinaryName方法
                if (clazz != null) {
                    return clazz;
                }
            }
        }
        return null;
    }
    /*package*/ static class Element {
        public final File file;
        public final ZipFile zipFile;
        public final DexFile dexFile;
        public Element(File file, ZipFile zipFile, DexFile dexFile) {
            this.file = file;
            this.zipFile = zipFile;
            this.dexFile = dexFile;
        }
    }
}

DexFile类分析

    private DexFile(String sourceName, String outputName, int flags) throws IOException {
        mCookie = openDexFile(sourceName, outputName, flags);
        mFileName = sourceName;
        guard.open("close");
        //System.out.println("DEX FILE cookie is " + mCookie);
    }
    static public DexFile loadDex(String sourcePathName, String outputPathName,
        int flags) throws IOException {
        return new DexFile(sourcePathName, outputPathName, flags);
    }
    public Class loadClass(String name, ClassLoader loader) {
        String slashName = name.replace('.', '/');
        return loadClassBinaryName(slashName, loader);
    }
    public Class loadClassBinaryName(String name, ClassLoader loader) {
        return defineClass(name, loader, mCookie); //调用defineClass本地方法
    }
    private native static Class defineClass(String name, ClassLoader loader, int cookie);

代码示例

示例1-不同类加载器

    @OnClick(R.id.startPlugina)
    void onStartPluginA() {
        /*Intent intent = new Intent(this, ProxyActivity.class);
        intent.putExtra(ProxyActivity.EXTRA_DEX_PATH, "/mnt/sdcard/DynamicLoadHost/dlapp-a.apk");
        startActivity(intent);*/
        Log.i("LiaBin", "Context的类加载加载器:" + Context.class.getClassLoader());//系统库的class,所以是BootClassLoader
        Log.i("LiaBin", "String的类加载加载器:" + String.class.getClassLoader());//系统库的class,所以是BootClassLoader,不同于java吧,java应用程序的话打印的是null
        Log.i("LiaBin", "MainActivity的类加载器:" + MainActivity.class.getClassLoader());//本地的class,所以是PathClassLoader
        Log.i("LiaBin", "StringRequest的类加载器:" + StringRequest.class.getClassLoader());//第三方库class,所以也是PathClassLoader。。v7,v4,recycleview中的也是第三方库哟
        Log.i("LiaBin", "应用程序默认加载器:" + getClassLoader()); //这才是默认的加载器DexPathList[[zip file "/data/app/demo.lbb.mytest-1.apk"]..
        Log.i("LiaBin", "系统类加载器:" + ClassLoader.getSystemClassLoader()); //上面代码可以知道此时是PathClassLoader,同时DexPathList[[directory "."]..

        Log.i("LiaBin", "系统类加载器和应用程序默认加载器是否相等:" + (getClassLoader() == ClassLoader.getSystemClassLoader())); //打印false
        Log.i("LiaBin", "自定义类和第三方类库使用的classloader和应用程序默认加载器是否相等:" + (MainActivity.class.getClassLoader() == getClassLoader())); 打印true

        Log.i("LiaBin", "打印应用程序默认加载器的委派机制:"); //parent是BootClassLoader
        ClassLoader classLoader = getClassLoader();
        while (classLoader != null) {
            Log.i("LiaBin", "类加载器:" + classLoader);
            classLoader = classLoader.getParent();
        }

        Log.i("LiaBin", "打印系统加载器的委派机制:"); //parent是BootClassLoader
        classLoader = ClassLoader.getSystemClassLoader();
        while (classLoader != null) {
            Log.i("LiaBin", "类加载器:" + classLoader);
            classLoader = classLoader.getParent();
        }

        try {
            ClassLoader.getSystemClassLoader().loadClass("demo.lbb.mytest.MainActivity"); //肯定是查找不到MainActivity的,因为SystemClassLoader的DexPathList为.,然后parent:BootClassLoader也找不到,因为MainActivity是自定义的嘛,如果此时换成""android.app.Activity",那就能找到了,因为parent:BootClassLoader加载了系统库的class
            Log.i("LiaBin", "系统默认加载器找到了MainActivity");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            Log.i("LiaBin", "系统默认加载器没找到MainActivity"); //打印此处
        }

        try {
            getClassLoader().loadClass("demo.lbb.mytest.MainActivity");
            Log.i("LiaBin", "应用程序默认加载器找到了MainActivity"); //打印此处
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            Log.i("LiaBin", "应用程序默认加载器没找到MainActivity");
        }
    }

打印结果:
I/LiaBin: Context的类加载加载器:java.lang.BootClassLoader@41cb45f0
I/LiaBin: String的类加载加载器:java.lang.BootClassLoader@41cb45f0
I/LiaBin: MainActivity的类加载器:dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/demo.lbb.mytest-1.apk”],nativeLibraryDirectories=[/data/app-lib/demo.lbb.mytest-1, /vendor/lib, /system/lib]]]
I/LiaBin: StringRequest的类加载器:dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/demo.lbb.mytest-1.apk”],nativeLibraryDirectories=[/data/app-lib/demo.lbb.mytest-1, /vendor/lib, /system/lib]]]
I/LiaBin: 应用程序默认加载器:dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/demo.lbb.mytest-1.apk”],nativeLibraryDirectories=[/data/app-lib/demo.lbb.mytest-1, /vendor/lib, /system/lib]]]
I/LiaBin: 系统类加载器:dalvik.system.PathClassLoader[DexPathList[[directory “.”],nativeLibraryDirectories=[/vendor/lib, /system/lib]]]
I/LiaBin: 系统类加载器和应用程序默认加载器是否相等:false
I/LiaBin: 自定义类和第三方类库使用的classloader和应用程序默认加载器是否相等:true
I/LiaBin: 打印应用程序默认加载器的委派机制:
I/LiaBin: 类加载器:dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/demo.lbb.mytest-1.apk”],nativeLibraryDirectories=[/data/app-lib/demo.lbb.mytest-1, /vendor/lib, /system/lib]]]
I/LiaBin: 类加载器:java.lang.BootClassLoader@41cb45f0
I/LiaBin: 打印系统加载器的委派机制:
I/LiaBin: 类加载器:dalvik.system.PathClassLoader[DexPathList[[directory “.”],nativeLibraryDirectories=[/vendor/lib, /system/lib]]]
I/LiaBin: 类加载器:java.lang.BootClassLoader@41cb45f0
I/LiaBin: 系统默认加载器没找到MainActivity
I/LiaBin: 应用程序默认加载器找到了MainActivity

简单看一下getClassLoader()方法的实现,我们知道实际上是ContextImpl

    @Override
    public ClassLoader getClassLoader() {
        return mPackageInfo != null ?
                mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
    }

mPackageInfo是个LoadedApk类型对象

    /**
     * Sets application info about the system package.
     */
    void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
        assert info.packageName.equals("android");
        mApplicationInfo = info;
        mClassLoader = classLoader;
    }

installSystemApplicationInfo在哪里调用就不清楚了,但是肯定不是ClassLoader.getSystemClassLoader()啦

示例2 –双亲委托模型

先看一下项目结构:

此时dlapp作为plugin.apk放在/mnt/sdcard/DynamicLoadHost/目录下
可以看到app项目有一个类lbb.test.dlapp.MainActivity,dlapp也有一个类lbb.test.dlapp.MainActivity,这两者类的路径完全相同,所以可以同时被加载吗?
答案是当然可以的,因为虚拟机中全限定名以及加载此类的ClassLoader来共同确定。也就是说即使两个类的全限定名是相同的,但是因为不同的 ClassLoader加载了此类,那么在JVM中它是不同的类

app中的MainActivity类

package lbb.test.dlapp;
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
    }

    public void printStr() {
        Log.d("LiaBin", "str from main----");
    }
}

dlapp中的类

package lbb.test.dlapp;
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void printStr() {
        Log.d("LiaBin", "str from plugin----");
    }
}

然后把dlapp编译成的plugin.apk放在/mnt/sdcard/DynamicLoadHost/目录下作为插件,app项目动态加载该插件

app项目的入口activity,此时也是MainActivity类,但是包名不一样了

package demo.lbb.mytest;
public class MainActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
    }
    @OnClick(R.id.startPlugin)
    void onStartPlugin() {
        String className = "lbb.test.dlapp.MainActivity";
        String mDexPath = "/mnt/sdcard/DynamicLoadHost/plugin.apk";
        File dexOutputDir = this.getDir("dex", 0);
        final String dexOutputPath = dexOutputDir.getAbsolutePath(); //data/data/..../app_dex目录下会有优化过后的dex文件
        ClassLoader localClassLoader = ClassLoader.getSystemClassLoader(); //拿到系统默认加载器
        //ClassLoader localClassLoader = getClassLoader(); //拿到应用程序默认加载器
        DexClassLoader dexClassLoader = new DexClassLoader(mDexPath,
                dexOutputPath, null, localClassLoader); // 因为是动态加载外部的,未安装,所以需要使用DexClassLoader加载器,同时此时设置parent
        try {
            Class<?> localClass = dexClassLoader.loadClass(className);
            Constructor<?> localConstructor = localClass
                    .getConstructor(new Class[]{});
            Object instance = localConstructor.newInstance(new Object[]{});
            Log.d("LiaBin", "onStartPlugin instance = " + instance);

            Method printStr = localClass.getMethod("printStr", new Class[]{});
            printStr.setAccessible(true);
            printStr.invoke(instance, new Object[]{});
        } catch (Exception e) {
            e.printStackTrace();
            Log.d("LiaBin", "startPlugin 发生异常");
        }
    }

    @OnClick(R.id.startPluginmain)
    void onStartPluginMain() {
        ClassLoader localClassLoader = getClassLoader(); //本项目中的lbb.test.dlapp.MainActivity直接使用应用程序加载器加载就行了,因为已经安装了在data/app/**目录下了
        try {
            Class<?> localClass = localClassLoader.loadClass("lbb.test.dlapp.MainActivity");
            Constructor<?> localConstructor = localClass
                    .getConstructor(new Class[]{});
            Object instance = localConstructor.newInstance(new Object[]{});
            Log.d("LiaBin", "onStartPluginMain instance = " + instance);
            Method printStr = localClass.getMethod("printStr", new Class[]{});
            printStr.setAccessible(true);
            printStr.invoke(instance, new Object[]{});
        } catch (Exception e) {
            e.printStackTrace();
            Log.d("LiaBin", "onStartPluginMain 发生异常");
        }
    }
}

情况1:ClassLoader localClassLoader = ClassLoader.getSystemClassLoader(); //拿到系统默认加载器
打印结果:
D/LiaBin: onStartPlugin instance = lbb.test.dlapp.MainActivity@42e105f8
D/LiaBin: str from plugin—-
D/LiaBin: onStartPluginMain instance = lbb.test.dlapp.MainActivity@42e14320
D/LiaBin: str from main—-

情况2:ClassLoader localClassLoader = getClassLoader(); //拿到应用程序默认加载器
D/LiaBin: onStartPlugin instance = lbb.test.dlapp.MainActivity@42d8edb8
D/LiaBin: str from main—-
D/LiaBin: onStartPluginMain instance = lbb.test.dlapp.MainActivity@42d92b50
D/LiaBin: str from main—-

看到区别了吗?onStartPlugin方法打印的结果不一样了
情况1,onStartPlugin方法调用的是dlapp中的mainactivity,因为parent是ClassLoader.getSystemClassLoader()系统默认加载器,此时parent中找不到mainactivity,所以最终会调用DexClassLoader的findclass方法

情况2,onStartPlugin方法调用的是app中的mainactivity,为什么呢?因为parent是getClassLoader()应用程序加载器,此时parent中有该mainactivity,所以

getClassLoader()); //应用程序DexPathList[[zip file “/data/app/demo.lbb.mytest-1.apk”]..

ClassLoader.getSystemClassLoader()); //系统默认加载器,此时也是PathClassLoader,但是DexPathList[[directory “.”]..所以如果有classloader把它当作parent的话,肯定找不到自定义的类的

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中的ClassLoader命名空间是指在Android应用程序中加载不同组件(如Activity、Service、BroadcastReceiver等)时的类加载环境和隔离机制。在Android中,每个应用程序组件都有自己的ClassLoader实例,用于加载和管理其依赖的类。 ClassLoader命名空间的主要作用是隔离不同应用程序组件之间的类加载,防止类的冲突和污染。每个应用程序组件运行在独立的ClassLoader实例中,这样它们就能够加载和使用自己的类,而不会被其他组件中的类所影响。 ClassLoader命名空间还提供了类加载的灵活性和扩展性。可以通过ClassLoader机制在不同的ClassLoader实例中加载不同版本的同一个类,从而避免了类的冲突。也可以使用自定义的ClassLoader实现自定义的类加载逻辑,例如从网络等外部来源加载类文件。 Android应用程序中的ClassLoader命名空间是由Android系统提供的ClassLoader框架实现的。在Android中,应用程序组件的ClassLoader实例是基于父类加载器(Parent ClassLoader)进行的,这样可以继承和共享父类加载器加载的类,提高类的加载效率和资源利用率。 总结来说,Android中的ClassLoader命名空间是为了实现应用程序组件之间的类加载隔离和灵活性而设计的,每个应用程序组件都有自己的ClassLoader实例,可以加载和管理自己的类。这种ClassLoader命名空间的设计使得Android应用程序能够在多组件环境下更加稳定和可扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值