• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android动态加载Dex机制解析

Android动态加载Dex机制解析

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android动态加载dex,android dex,android dex分包方案,android dex分包,android dex文件等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android动态加载Dex机制解析


1.什么是类加载器?

类加载器(class loader)是 Java?中的一个很重要的概念。类加载器负责加载 Java 类的字节代码到 Java 虚拟机中。
Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。
 

2.Dalvik虚拟机类加载机制

Dalvik虚拟机如同其他Java虚拟机一样,在运行程序时首先需要将对应的类加载到内存中。而在Java标准的虚拟机中,类加载可以从class文件中读取,也可以是其他形式的二进制流,因此,我们常常利用这一点,在程序运行时手动加载Class,从而达到代码动态加载执行的目的,但是Dalvik虚拟机毕竟不算是标准的Java虚拟机,因此在类加载机制上,它们有相同的地方,也有不同之处。</div>  </div> 我们先看下下面这张关于Android Classload机制的图。</div>  </div> </div>  </div>

与JVM不同,Dalvik的虚拟机不能用ClassCload直接加载.dex,Android从ClassLoader派生出了两个类:DexClassLoader和PathClassLoader;而这两个类就是我们加载dex文件的关键,这两者的区别是:

1.DexClassLoader:可以加载jar/apk/dex,可以从SD卡中加载未安装的apk;
2.PathClassLoader:要传入系统中apk的存放Path,所以只能加载已经安装的apk文件。

准备工作开始

一、打开Android studio 新建工程:</div> </div>  </div>  </div> 工程目录是这样的:</div> </div>  </div> 动态加载进来的class如何使用,一般有2种办法,一种是使用反射调用,这种我不多做介绍;还有一种是使用接口编程的方式来调用对应的方法,毕竟.dex文件也是我们自己维护的,所以可以把方法抽象成公共接口,把这些接口也复制到主项目里面去,就可以通过这些接口调用动态加载得到的实例的方法了。</div> 接下来我们源码包下面新建一个包名称是dynamic,然后在dynamic下新建一个interface接口Dynamic,里面有个接口方法,就叫sayHello()吧,返回一个String,到时候我们可以通过Toast弹出来,Dynamic.java:</div>
package wangyang.zun.com.mydexdemo.dynamic;

/**
 * Created by WangYang on 2016/3/11.
 */
public interface Dynamic {
    String sayHello();
}
接着我们新建一个impl包,并实现Dynamic接口,DynamicImpl.java:</div>
package wangyang.zun.com.mydexdemo.dynamic.impl;

import wangyang.zun.com.mydexdemo.dynamic.Dynamic;

/**
 * Created by WangYang on 2016/3/11.
 */
public class DynamicImpl implements Dynamic {

    @Override
    public String sayHello() {
        return new StringBuilder(getClass().getName()).append(" is loaded by DexClassLoader").toString();
    }
}
很简单输出一句话,"DynamicImpl is loaded by DexClassLoader."</div> 具体的工程目录如下图:</div> </div>  </div> </div> 点击Build -> make project,这时候会在build\intermediates\classes\debug目录下生成对应的classes文件。</div>  </div> </div>  </div> 好了我们要把DynamicImpl这个class转换成Dalvik可识别的dex文件,分两步:</div> 1.先导出DynamicImpl这个类为jar包的形式;</div> 2.通过android sdk自带的dx.jar工具转换jar包为dex文件。</div> 完成第一步,当时遇到点麻烦,由于eclipse是基于ant并且有可视化工具,可以直接导出指定文件的jar包,但是android studio不行,那怎么办呢?</div> 我们可以通过gradle task来打包,打开app目录下的build.gradle文件,切记不是根目录的build.gradle文件,加上以下代码:</div>
//删除dynamic.jar包任务
task clearJar(type: Delete) {
    delete 'libs/dynamic.jar'
}

//打包任务
task makeJar(type:org.gradle.api.tasks.bundling.Jar) {
    //指定生成的jar名
    baseName 'dynamic'
    //从哪里打包class文件
    from('build/intermediates/classes/debug/wangyang/zun/com/mydexdemo/dynamic/')
    //打包到jar后的目录结构
    into('wangyang/zun/com/mydexdemo/dynamic/')
    //去掉不需要打包的目录和文件
    exclude('test/', 'Dynamic.class', 'BuildConfig.class', 'R.class')
    //去掉R$开头的文件
    exclude{ it.name.startsWith('R$');}
}
makeJar.dependsOn(clearJar, build)

打开AS的 terminal窗口: cd app进入app目录,执行gradle makeJar,然后等待直到出现Build Successfully,这时会在build目录下出现libs/dynamic.jar文件,这个文件就是我们要用的jar包,我们可以使用jd-gui打开看下是不是只有DynamicImpl这个class;</div> 第二步,使用sdk提供的dx.jar将导出的dynamic.jar转换成Dalvik可识别的dex格式,新版的sdk已经将dx.jar放到build-tools\23.0.2\lib目录下,我们在dos下或者在Android studio terminal下面进入到此目录,然后运行下面的命令:</div> </div> </div>  </div> output是你的输出目录,默认就是在当前的根目录下,执行完成后我们就在当前目录下生成了Davilk虚拟机可执行的dex文件,因为这条命令同时会打包dex文件,因此后缀是jar,我们用jd-gui打开dynamic.jar和dynamic_dex.jar这两个文件,看下他们有的结构。</div>  </div> </div>  </div>  </div> </div>  </div> 可以看到,打包后的文件其实是一个classes.dex文件,目前为止我们要做的工作已经准备就绪了,接下来就是要在demo中使用这个dex文件。</div>  </div> 二、删除刚刚新建的impl包以及包内的文件:</div> 因为等下我们要使用的是dex下面的IDynamic实现类,所以我们需要删除当前工程下的IDynamic.java文件和impl包,避免运行时出错。同时,我们要把刚刚生成的dynamic_dex.jar文件放到assets目录下,等下需要把它copy到app/data下使用,删除后的整个工程目录如下:</div>  </div> </div>  </div> FileUtils类是从assets目录下copy文件到app/data/cache目录,源码如下:</div>
public class FileUtils {

    public static void copyFiles(Context context, String fileName, File desFile) {
        InputStream in = null;
        OutputStream out = null;
        try {
            in = context.getApplicationContext().getAssets().open(fileName);
            out = new FileOutputStream(desFile.getAbsolutePath());
            byte[] bytes = new byte[1024];
            int i;
            while ((i = in.read(bytes)) != -1)
                out.write(bytes, 0 , i);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (in != null)
                    in.close();
                if (out != null)
                    out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    public static boolean hasExternalStorage() {
        return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
    }

    /**
     * 获取缓存路径
     *
     * @param context
     * @return 返回缓存文件路径
     */
    public static File getCacheDir(Context context) {
        File cache;
        if (hasExternalStorage()) {
            cache = context.getExternalCacheDir();
        } else {
            cache = context.getCacheDir();
        }
        if (!cache.exists())
            cache.mkdirs();
        return cache;
    }

}
</div> <
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android动态加载Dex机制解析

相关文章

  • 2017-05-26viewPager使用时加载数据时显示IllegalStateException异常,解决不了。。。。,viewpager取消预加载
  • 2017-05-26设计五(六)大原则,设计原则
  • 2017-05-26Android开源项目分类汇总(六)工具库
  • 2017-05-26安卓下如何使用JUnit进行软件测试,安卓junit
  • 2017-05-26安卓四大组件之广播,安卓四大组件
  • 2017-05-26Apk去掉签名以及重新签名的方法,apk去掉签名
  • 2017-05-26高仿it之家新闻客户端源码,高仿it之家源码
  • 2017-05-26【读书笔记】【Android 开发艺术探索】第3章 View 的事件体系
  • 2017-11-18android开发使用组件心得
  • 2017-05-26NDK中使用pthread多线程中自己写的一个BUG,ndkpthread

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • android MediaPlayer 错误代码(error code)总结 转载,androidmediaplayer
    • Android中Activity处理返回结果的实现方式,androidactivity
    • 找不到draw9patch.bat?已经不用找了,draw9patch.bat
    • 自动匹配关键字并且标红,匹配关键字标红
    • Android6.0权限管理
    • Android对应用程序签名,android签名
    • Android中Fragment的两种创建方式,androidfragment
    • 自定义收集用户行为统计库 (非常方便 可以自己拓展)
    • Android:应用宝省流量更新
    • Activity 启动模式,activity启动模式

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有