ClassLoader和热更新

2018-09-30  本文已影响0人  NullBugs

标签(空格分隔): classloader multidex 热更新


前言:Android P的发布,使得一大批使用第三方热更新框架的APP一片哀嚎(核心原因是:Android P 禁止应用通过反射,JNI等方式调用系统的非SDK方法,第三框架或多或少都用到了反射,在Android P上APP的功能失效)
感谢磊神分享

Java Classloader

20170210192931505.png

类的继承关系:

注:
ExtClassLoader.java 和 AppClassLoader.java本身不具有类的继承关系,他们共同继承URLClassLoader.java

    /*
     * Returns the class loader used to launch the main application.
     */
    public ClassLoader getClassLoader() {
        return loader;
    }
    /*
     * The class loader used for loading installed extensions.
     */
    static class ExtClassLoader extends URLClassLoader {}

/**
     * The class loader used for loading from java.class.path.
     * runs in a restricted security context.
     */
    static class AppClassLoader extends URLClassLoader {}

Parent通过ExtClassLoader 构建 APPClassLoader:

        ClassLoader extcl;
        try {
            extcl = ExtClassLoader.getExtClassLoader();
        } catch (IOException e) {
            throw new InternalError(
                "Could not create extension class loader", e);
        }

        // Now create the class loader to use to launch the application
        try {
        //将ExtClassLoader对象实例传递进去
            loader = AppClassLoader.getAppClassLoader(extcl);
        } catch (IOException e) {
            throw new InternalError(
                "Could not create application class loader", e);
        }
1071527397.jpg

ClassLoader 测试代码

        ClassLoader appClassLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println("app ClassLoader : " + appClassLoader);
        System.out.println("app ClassLoader class : " + appClassLoader.getClass());
        System.out.println("app ClassLoader load Path : " + System.getProperty("java.class.path"));
        
        System.out.println("-------------------------");
    
        ClassLoader extClassLoader = appClassLoader.getParent();
        System.out.println("ext ClassLoader : " + extClassLoader);
        System.out.println("ext ClassLoader class : " + extClassLoader.getClass());
        System.out.println("ext ClassLoader load Path : " + System.getProperty("java.ext.dirs"));
        
        System.out.println("-------------------------");

        ClassLoader bootClassLoader = extClassLoader.getParent();
        System.out.println("boot ClassLoader : " + bootClassLoader);
        System.out.println("boot ClassLoader load Path : " +(System.getProperty("sun.boot.class.path")));

执行结果如下:

app ClassLoader : sun.misc.Launcher$AppClassLoader@c387f44
app ClassLoader class : class sun.misc.Launcher$AppClassLoader
app ClassLoader load Path : D:\Android_work\java\ClassLoaderTest\bin
-------------------------
ext ClassLoader : sun.misc.Launcher$ExtClassLoader@659e0bfd
ext ClassLoader class : class sun.misc.Launcher$ExtClassLoader
ext ClassLoader load Path : D:\soft\devsoft\soft\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
-------------------------
boot ClassLoader : null
boot ClassLoader load Path : D:\soft\devsoft\soft\jre\lib\resources.jar;D:\soft\devsoft\soft\jre\lib\rt.jar;D:\soft\devsoft\soft\jre\lib\sunrsasign.jar;D:\soft\devsoft\soft\jre\lib\jsse.jar;D:\soft\devsoft\soft\jre\lib\jce.jar;D:\soft\devsoft\soft\jre\lib\charsets.jar;D:\soft\devsoft\soft\jre\lib\jfr.jar;D:\soft\devsoft\soft\jre\classes

为什么要引入父委托加载机制

 /**
     * Copy characters from this string into dst starting at dstBegin.
     * This method doesn't perform any range checking.
     */
    void getChars(char dst[], int dstBegin) {
        System.arraycopy(value, 0, dst, dstBegin, value.length);
    }

Android Classloader

192717809.jpg 337439105.jpg 1854581320.jpg

Android Multidex(分包)

304680740.jpg
- 解决65535问题
203851534.jpg
在android 5.0之前,DVM虚拟机用short类型的变量保存了一个dex文件中的方法数,所以最大值是65535
带包名的类转dex注意: 最后一个参数应当携带包的相对路径,例如:
dx –-dex –-output=xxx.dex 包名/xxx.class

基于类加载器实现的简单热更新Demo

准备操作:生成补丁文件与搭建后台

第一种实现

第二种实现

结语:第三方热更新的框架基本都是通过这两种方式实现热更新,但是在Android P上或多或少都存在问题,建议大家尽量使用Android 标准的接口,原因在于Android逐渐加强了系统安全控制,第三方框架或多或少有很多灰色地带。

参考

android mutidex的原理和实现

上一篇 下一篇

猜你喜欢

热点阅读