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

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

  • 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号晚

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值