Android动态类生成预加载-dexmaker使用
一、dexmaker简单介绍
dexmaker是运行在Android Dalvik VM上,利用Java编写,来动态生成DEX字节码的API。如果读者了解AOP编程的话,应该听说过cglib or ASM,但这两个工具生成都是Java字节码,而Dalvik加载的必须是DEX字节码。所以,想要在Android上进行AOP编程,dexmaker可以说是一个很好的选择。项目地址:https://github.com/crittercism/dexmaker。
二。简单使用
下面这个例子非常典型,可以说入门非常好了。过程很简单,生成一个包含一个函数的类,在主程序里面动态加载(使用ClassLoader),然后执行类里面的函数。这是在Java平台的例子,我直接在Android上进行编程的,后面或说明相应的问题以及解决办法,下来看看这个例子吧。
public final class HelloWorldMaker {
public static void main(String[] args) throws Exception {
DexMaker dexMaker = new DexMaker();
// Generate a HelloWorld class.
TypeId<?> helloWorld = TypeId.get("LHelloWorld;");
dexMaker.declare(helloWorld, "HelloWorld.generated", Modifier.PUBLIC, TypeId.OBJECT);
generateHelloMethod(dexMaker, helloWorld);
// Create the dex file and load it.
File outputDir = new File(".");
ClassLoader loader = dexMaker.generateAndLoad(HelloWorldMaker.class.getClassLoader(),
outputDir, outputDir);
Class<?> helloWorldClass = loader.loadClass("HelloWorld");
// Execute our newly-generated code in-process.
helloWorldClass.getMethod("hello").invoke(null);
}
private static void generateHelloMethod(DexMaker dexMaker, TypeId<?> declaringType) {
// Lookup some types we'll need along the way.
TypeId<System> systemType = TypeId.get(System.class);
TypeId<PrintStream> printStreamType = TypeId.get(PrintStream.class);
// Identify the 'hello()' method on declaringType.
MethodId hello = declaringType.getMethod(TypeId.VOID, "hello");
// Declare that method on the dexMaker. Use the returned Code instance
// as a builder that we can append instructions to.
Code code = dexMaker.declare(hello, Modifier.STATIC | Modifier.PUBLIC);
// Declare all the locals we'll need up front. The API requires this.
Local<Integer> a = code.newLocal(TypeId.INT);
Local<Integer> b = code.newLocal(TypeId.INT);
Local<Integer> c = code.newLocal(TypeId.INT);
Local<String> s = code.newLocal(TypeId.STRING);
Local<PrintStream> localSystemOut = code.newLocal(printStreamType);
// int a = 0xabcd;
code.loadConstant(a, 0xabcd);
// int b = 0xaaaa;
code.loadConstant(b, 0xaaaa);
// int c = a - b;
code.op(BinaryOp.SUBTRACT, c, a, b);
// String s = Integer.toHexString(c);
MethodId<Integer, String> toHexString
= TypeId.get(Integer.class).getMethod(TypeId.STRING, "toHexString", TypeId.INT);
code.invokeStatic(toHexString, s, c);
// System.out.println(s);
FieldId<System, PrintStream> systemOutField = systemType.getField(printStreamType, "out");
code.sget(systemOutField, localSystemOut);
MethodId<PrintStream, Void> printlnMethod = printStreamType.getMethod(
TypeId.VOID, "println", TypeId.STRING);
code.invokeVirtual(printlnMethod, null, localSystemOut, s);
// return;
code.returnVoid();
}
}
generateHelloMethod函数生成的函数是:
public static void hello() {
int a = 0xabcd;
int b = 0xaaaa;
int c = a - b;
String s = Integer.toHexString(c);
System.out.println(s);
return;
}
这里很关键的是变量的声明与赋值和函数的声明与调用。例如int变量声明:
Local<Integer> a = code.newLocal(TypeId.INT);
变量赋值:
code.loadConstant(a, 0xabcd);
函数声明:
MethodId<Integer, String> toHexString = TypeId.get(Integer.class).getMethod(TypeId.STRING, "toHexString", TypeId.INT);
函数调用:
code.invokeStatic(toHexString, s, c);
过程非常简单,要生成一个完整的简单的类按照此步骤能很快完成。好的,现在进入正片部分了,即在Android平台使用dexmaker的情况。
Android动态类生成预加载-dexmaker使用的更多相关文章
- Unity3D 游戏开发构架篇 —— 动态大场景生成 = 区域加载+对象池管理
项目做一个类似无尽模式的场景,想了一想,其实方法很简单,做一个相关的总结. 主要先谈一谈构架,后期附上代码. 一.区域加载 其实无尽场景的实现很简单,因为屏幕限制,那么不论何时何地,我们只能看到自己的 ...
- Android viewpager + fragment取消预加载
1,在fragment中重写setUserVisibleHint方法private boolean isVisibleToUser;@Overridepublic void setUserVisibl ...
- Android中ViewPager+Fragment取消(禁止)预加载延迟加载(懒加载)问题解决方案
转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53205878本文出自[DylanAndroid的博客] Android中Vie ...
- 通过link的preload进行内容预加载
Preload 作为一个新的web标准,旨在提高性能和为web开发人员提供更细粒度的加载控制.Preload使开发者能够自定义资源的加载逻辑,且无需忍受基于脚本的资源加载器带来的性能损失. <l ...
- HBuilder mui 手机app开发 Android手机app开发 ios手机app开发 打开新页面 预加载页面 关闭页面
创建子页面 在mobile app开发过程中,经常遇到卡头卡尾的页面,此时若使用局部滚动,在android手机上会出现滚动不流畅的问题: mui的解决思路是:将需要滚动的区域通过单独的webview实 ...
- android viewpage预加载和懒加载问题
1.本人理解懒加载和预加载问题某种情况下可以归结为一类问题,下面我就说一下我遇到的预加载问题和懒加载问题及解决的相应方法: - [1 ] 预加载问题 描述:我用到了三个fragment. ...
- JAVA类的静态加载和动态加载以及NoClassDefFoundError和ClassNotFoundException
我们都知道Java初始化一个类的时候可以用new 操作符来初始化, 也可通过Class.forName()的方式来得到一个Class类型的实例,然后通过这个Class类型的实例的newInstance ...
- PHP+Mysql+easyui点击左侧tree菜单对应表名右侧动态生成datagrid加载表单数据(二)
关于tree菜单生成,参考我的另一篇博文地址tree 菜单 实现功能:点击左侧tree菜单中的table,右侧通过datagrid加载出该表对用的所有数据 难点:获取该表的所有列名,动态生成datag ...
- 如何使用SVG生成超酷的页面预加载素描动画效果
在线演示 本地下载 1 SVG简介 可缩放矢量图形是基于可扩展标记语言(标准通用标记语言的子集),用于描述二维矢量图形的一种图形格式.它由万维网联盟制定,是一个开放标准. 2 SVG的特点 与其他图像 ...
随机推荐
- VS2008集成PC-lint
引言 C/C++语言的语法拥有其它语言所没有的灵活性,这种灵活性带来了代码效率的提升,但相应也使得代码编写具有很大的随意性,另外C/C++编译器不进行强制类型检查,也不做任何边界检查,这就增加了代码中 ...
- ECMAScript 6 笔记(一)
一.ECMAScript 6简介 1996年11月,JavaScript的创造者Netscape公司,决定将JavaScript提交给国际标准化组织ECMA,希望这种语言能够成为国际标准.次年,ECM ...
- linux下ACE的编译与安装
1.环境变量的设置vim /etc/profile 2.然后输入export ACE_ROOT=/root/ACE/ACE_wrappers export MPC_ROOT=$ACE_ROOT/MPC ...
- 优雅使用 illuminate/database 包中的 Collection
优雅使用 illuminate/database 包中的 Collection 或许你很抵抗使用 Laravel , 但是你没有理由不喜欢使用 illuminate/database.这是一个 ORM ...
- linux、windows系统间传输文件
日常工作中经常涉及到系统间的文件传输,下面就简单说一下常用的方法 linux--windows 工具:winscp.SecureCRT.Zmodem(sz, rz) linux--l ...
- 一种解决eclipse中安装maven出错的方法
1.安装步骤:https://jingyan.baidu.com/article/a17d5285feb4dd8099c8f26e.html 2.安装第三步的解决办法:m2e 路径换成 http ...
- Yii2中JSONP跨域问题的解决
Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据. 为什么我们从不同的域(网站)访问数据需 ...
- Redis 设置开机启动
1. 将下列代码保存为文件redis, 置于 /etc/init.d 下面 ########################### # chkconfig: 2345 90 10 redis服务必须在 ...
- 思科ASA5520防火墙telnet、SSH及DHCP设置
ASA5520远程登录telnet 注:最低安全级别的接口不支持telnet登陆,如OutsideASA(config)# telnet 172.16.0.0 255.255.0.0 inside ...
- Nginx HTTP模块指令
alias 指令 该指令用于在url和系统路径之间的映射. location /a/{ alias /b/; } error_page 定义错误页面 error_page 404 /404.html; ...