Android动态载入Dex机制解析
1.什么是类载入器?
类载入器(class loader)是 Java™中的一个非常重要的概念。类载入器负责载入 Java 类的字节代码到 Java 虚拟机中。
Java 虚拟机使用 Java 类的方式例如以下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类载入器负责读取 Java 字节代码,并转换成java.lang.Class类的一个实例。每一个这种实例用来表示一个 Java 类。通过此实例的 newInstance()方法就能够创建出该类的一个对象。实际的情况可能更加复杂。比方 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。
基本上全部的类载入器都是 java.lang.ClassLoader类的一个实例,须要了解ClassLoader能够參考这篇文章深入ClasssLoader
2.Dalvik虚拟机类载入机制
而在Java标准的虚拟机中。类载入能够从class文件里读取。也能够是其它形式的二进制流,因此。我们经常利用这一点,在程序执行时手动载入Class,从而达到代码动态载入执行的目的,可是Dalvik虚拟机毕竟不算是标准的Java虚拟机,因此在类载入机制上。它们有同样的地方。也有不同之处。

与JVM不同,Dalvik的虚拟机不能用ClassCload直接载入.dex,Android从ClassLoader派生出了两个类:DexClassLoader和PathClassLoader;而这两个类就是我们载入dex文件的关键,这两者的差别是:
1.DexClassLoader:能够载入jar/apk/dex。能够从SD卡中载入未安装的apk;
2.PathClassLoader:要传入系统中apk的存放Path,所以仅仅能载入已经安装的apk文件。
关于Android 动态载入基础 ClassLoader工作机制大家能够參考这里:https://segmentfault.com/a/1190000004062880。
准备工作開始
package wangyang.zun.com.mydexdemo.dynamic; /**
* Created by WangYang on 2016/3/11.
*/
public interface Dynamic {
String sayHello();
}
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();
}
}
非常easy输出一句话,"DynamicImpl is loaded by DexClassLoader."
//删除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。
同一时候,我们要把刚刚生成的dynamic_dex.jar文件放到assets文件夹下,等下须要把它copy到app/data下使用。删除后的整个project文件夹例如以下:
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;
}
}
public class MainActivity extends AppCompatActivity {
private Dynamic dynamic;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//加入一个点击事件
findViewById(R.id.tx).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loadDexClass();
}
});
}
/**
* 载入dex文件里的class,并调用当中的sayHello方法
*/
private void loadDexClass() {
File cacheFile = FileUtils.getCacheDir(getApplicationContext());
String internalPath = cacheFile.getAbsolutePath() + File.separator + "dynamic_dex.jar";
File desFile = new File(internalPath);
try {
if (!desFile.exists()) {
desFile.createNewFile();
FileUtils.copyFiles(this, "dynamic_dex.jar", desFile);
}
} catch (IOException e) {
e.printStackTrace();
}
//以下開始载入dex class
DexClassLoader dexClassLoader = new DexClassLoader(internalPath, cacheFile.getAbsolutePath(), null, getClassLoader());
try {
Class libClazz = dexClassLoader.loadClass("wangyang.zun.com.mydexdemo.dynamic.impl.IDynamic");
dynamic = (Dynamic) libClazz.newInstance();
if (dynamic != null)
Toast.makeText(this, dynamic.sayHelloy(), Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Android动态载入Dex机制解析的更多相关文章
- Android动态载入JAR包的实现方法
有时候我们须要使用动态更新技术,简单来说就是:当我们把开发jar包发送给用户后.假设后期升级了部分代码.这时让用户的jar包自己主动更新,而不是用户主动手动地去更新的技术就是动态更新.这个须要使用的技 ...
- 深入浅出Android动态载入jar包技术
在实际项目中.因为某些业务频繁变更而导致频繁升级client的弊病会造成较差的用户体验,而这也恰是Web App的优势,于是便衍生了一种思路.将核心的易于变更的业务封装在jar包里然后通过网络下载下来 ...
- [转载] Android动态加载Dex机制解析
本文转载自: http://blog.csdn.net/wy353208214/article/details/50859422 1.什么是类加载器? 类加载器(class loader)是 Java ...
- 实现Android 动态载入APK(Fragment or Activity实现)
尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38565345 近期由于项目太大了.导致编译通只是(Android对一个应用中的方法个数貌似有 ...
- Android Touch事件传递机制解析 (推荐)
最近新闻列表里的下拉 down up move 等等让我十分头疼 ,无意间看到了一篇非常不错的帖子,转载如下: 开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把a ...
- Android Touch事件传递机制解析
android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean dispatchTouchEvent(MotionEven ...
- Android 使用动态载入框架DL进行插件化开发
如有转载,请声明出处: 时之沙: http://blog.csdn.net/t12x3456 (来自时之沙的csdn博客) 概述: 随着应用的不断迭代.应用的体积不断增大,项目越来越臃肿,冗余添 ...
- DL动态载入框架技术文档
DL动态载入框架技术文档 DL技术交流群:215680213 1. Android apk动态载入机制的研究 2. Android apk动态载入机制的研究(二):资源载入和activity生命周期管 ...
- Android 动态加载 (二) 态加载机制 案例二
探秘腾讯Android手机游戏平台之不安装游戏APK直接启动法 重要说明 在实践的过程中大家都会发现资源引用的问题,这里重点声明两点: 1. 资源文件是不能直接inflate的,如果简单的话直接在程序 ...
随机推荐
- 在oracle官网上,找到我们所需版本的jdk
oracle的官网,因为都是英文,而且内容还特别多,经常的找不到历史版本的JDK. 特地,将找历史版本JDK的方法记录下来. 访问:http://www.oracle.com/technetwork/ ...
- Selenium2+python自动化49-判断文本(text_to_be_present_in_element)【转载】
前言 在做结果判断的时候,经常想判断某个元素中是否存在指定的文本,如登录后判断页面中是账号是否是该用户的用户名. 在前面的登录案例中,写了一个简单的方法,但不是公用的,在EC模块有个方法是可以专门用来 ...
- [BZOJ3585]mex 主席树
3585: mex Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1252 Solved: 639[Submit][Status][Discuss] ...
- 使用 gulp 压缩图片
请务必理解如下章节后阅读此章节: 安装 Node 和 gulp 使用 gulp 压缩 JS 压缩 图片文件可降低文件大小,提高图片加载速度. 找到规律转换为 gulp 代码 规律 找到 images/ ...
- 图解Javascript——执行上下文
什么是执行上下文? 执行上下文(Execution Context)是ECMAScript规范中用来描述 JavaScript 代码执行的抽象概念,规定了当前代码执行的环境(当前执行代码片段中的变量. ...
- MySQL插入中文数据报错
在操作数据库插入中文会出现如下错误: ERROR 1366 (HY000): Incorrect string value: '\xC4\xE3\xBA\xC3' for column 'userna ...
- python+selenium 组织用例方式 总结
1.unittest.main() 将一个单元测试模块变为可直接运行的测试脚本,main()方法使用TestLoader类来搜索所有包含在该模块中以“test”命名开头的测试方法,并自动执行他们.执行 ...
- 完全背包【p1832】A+B Problem(再升级)
Description 给定一个正整数n,求将其分解成若干个素数之和的方案总数. Input 一行:一个正整数n Output 一行:一个整数表示方案总数 素数之和 ? 背包啊. 没一遍切的题都不是水 ...
- 8.5(java学习笔记)8.5 字节码操作(javassist)
一.javassist javassist让我们操作字节码更加简单,它是一个类库,允许我们修改字节码.它允许java程序动态的创建.修改类. javassist提供了两个层次的API,基于源码级别的和 ...
- 7.2(java学习笔记)URL
一.URL URL类表示统一资源定位符,指向万维网上“资源”的指针. 资源可以是简单的文件或目录,也可以是对更复杂对象的引用,比如对数据库或搜索引擎的查询. URL即是定位也是资源,定位到网络中一个具 ...