Android类加载器-动态加载外部dex

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lwj_zeal/article/details/89195520

Android 类加载

Android 只能加载识别 dex 文件,因此需要将 .java 文件编译 .class 文件,然后将 .class 优化为 .dex 文件。

过程:.java -> .class -> .dex

下面来练习如何去加载一个 dex 文件,并调用 dex 中的方法。

获取需要动态加载的 dex 文件

  • 编写 DynamicClass.java 类
public class DynamicClass {
    public static void main(String[] args){
        print();
    }

    public static void print() {
        System.out.println("Hello Dynamic");
    }
}
  • 编译 DynamicClass.java

编译后会得到 DynamicClass.class,注意:我这里将环境变量 JAVA_HOME 指定为 JDK1.6,不然用 dx 转化编译出来的 class 可能有一些奇怪的问题。

javac DynamicClass.java
  • 优化 class 文件得到 dex 文件

Android SDK 提供了 dx 工具,可以将 class 转化为 dex 文件。

dx 工具位于:build-tools/23.0.2/dx 23.0.2是版本号,build-tools 下有很多版本,随便选一个即可。

dx

将 DynamicClass.class 转化为 dex 文件 dynamic.dex

dx --dex --output=dynamic.dex DynamicClass.class
  • dynamic.dex 上传到 /sdcard 根目录下
adb push dynamic.dex /sdcard

加载并调用.dex里面的方法

Android 中加载 dex 文件是通过以下两种类加载器 DexClassLoader 或者 PathClassLoader 来加载的。

  • DexClassLoader

可以加载含有 dex 文件的 jar 或者 apk 文件,也可以从 SD卡 中加载未安装的 apk;

DexClassLoader

扫描二维码关注公众号,回复: 5840377 查看本文章
  • PathClassLoader

加载已经安装的apk文件。

PathClassLoader

DexClassLoader

因为我们是需要外部动态加载 dex 文件,因此只能使用 DexClassLoader 来加载 dex 文件了。

  • 指定存放 dex 文件的路径

在上面的步骤中,我们已经将生成的 dex 文件拷贝到 sdcard 目录下了。

String dexPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "dynamic.dex";

构造一个 DexClassLoader

DexClassLoader dexClassLoader = new DexClassLoader(dexPath, 
Environment.getExternalStorageDirectory().toString(), null, loader);
  • 加载 dex 文件中的类 DynamicClass
Class dynamicClass = dexClassLoader.loadClass("DynamicClass");
  • 反射调用 DynamicClass 的 print() 方法
Method printMethod = dynamicClass.getMethod("print");
printMethod.invoke(dynamicClass.newInstance());

DynamicClass 类完整的代码如下:

public class DexLoader {

    public static void dynamicLoad(ClassLoader loader) {

        //动态加载 dex
        String dexPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "dynamic.dex";
        System.out.println(dexPath);
        DexClassLoader dexClassLoader = new DexClassLoader(dexPath, Environment.getExternalStorageDirectory().toString(), null, loader);

        try {
            Class dynamicClass = dexClassLoader.loadClass("DynamicClass");
            Method printMethod = dynamicClass.getMethod("print");

            printMethod.invoke(dynamicClass.newInstance());

            System.out.println("动态加载成功");

        } catch (Exception e) {
            e.printStackTrace();

            System.out.println("动态加载失败:" + e.toString());
        }
    }
}

项目地址:https://github.com/liaowjcoder/study4Java/blob/master/classloader/src/main/java/com/example/classloader/DexLoader.java

记录于 2019年4月10号晚

猜你喜欢

转载自blog.csdn.net/lwj_zeal/article/details/89195520