• 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上进行编程的,后面或说明相应的问题以及解决办法,下来看看这个例子吧。

     1 public final class HelloWorldMaker {
     2     public static void main(String[] args) throws Exception {
     3         DexMaker dexMaker = new DexMaker();
     4 
     5         // Generate a HelloWorld class.
     6         TypeId<?> helloWorld = TypeId.get("LHelloWorld;");
     7         dexMaker.declare(helloWorld, "HelloWorld.generated", Modifier.PUBLIC, TypeId.OBJECT);
     8         generateHelloMethod(dexMaker, helloWorld);
     9 
    10         // Create the dex file and load it.
    11         File outputDir = new File(".");
    12         ClassLoader loader = dexMaker.generateAndLoad(HelloWorldMaker.class.getClassLoader(),
    13                 outputDir, outputDir);
    14         Class<?> helloWorldClass = loader.loadClass("HelloWorld");
    15 
    16         // Execute our newly-generated code in-process.
    17         helloWorldClass.getMethod("hello").invoke(null);
    18     }
    19 
    20     private static void generateHelloMethod(DexMaker dexMaker, TypeId<?> declaringType) {
    21         // Lookup some types we'll need along the way.
    22         TypeId<System> systemType = TypeId.get(System.class);
    23         TypeId<PrintStream> printStreamType = TypeId.get(PrintStream.class);
    24 
    25         // Identify the 'hello()' method on declaringType.
    26         MethodId hello = declaringType.getMethod(TypeId.VOID, "hello");
    27 
    28         // Declare that method on the dexMaker. Use the returned Code instance
    29         // as a builder that we can append instructions to.
    30         Code code = dexMaker.declare(hello, Modifier.STATIC | Modifier.PUBLIC);
    31 
    32         // Declare all the locals we'll need up front. The API requires this.
    33         Local<Integer> a = code.newLocal(TypeId.INT);
    34         Local<Integer> b = code.newLocal(TypeId.INT);
    35         Local<Integer> c = code.newLocal(TypeId.INT);
    36         Local<String> s = code.newLocal(TypeId.STRING);
    37         Local<PrintStream> localSystemOut = code.newLocal(printStreamType);
    38 
    39         // int a = 0xabcd;
    40         code.loadConstant(a, 0xabcd);
    41 
    42         // int b = 0xaaaa;
    43         code.loadConstant(b, 0xaaaa);
    44 
    45         // int c = a - b;
    46         code.op(BinaryOp.SUBTRACT, c, a, b);
    47 
    48         // String s = Integer.toHexString(c);
    49         MethodId<Integer, String> toHexString
    50                 = TypeId.get(Integer.class).getMethod(TypeId.STRING, "toHexString", TypeId.INT);
    51         code.invokeStatic(toHexString, s, c);
    52 
    53         // System.out.println(s);
    54         FieldId<System, PrintStream> systemOutField = systemType.getField(printStreamType, "out");
    55         code.sget(systemOutField, localSystemOut);
    56         MethodId<PrintStream, Void> printlnMethod = printStreamType.getMethod(
    57                 TypeId.VOID, "println", TypeId.STRING);
    58         code.invokeVirtual(printlnMethod, null, localSystemOut, s);
    59 
    60         // return;
    61         code.returnVoid();
    62     }
    63 }

      generateHelloMethod函数生成的函数是:

    
    
    1        public static void hello() {
    2              int a = 0xabcd;
    3              int b = 0xaaaa;
    4              int c = a - b;
    5             String s = Integer.toHexString(c);
    6             System.out.println(s);
    7             return;
    8         }

    这里很关键的
    是变量的声明与赋值和函数的声明与调用。例如int变量声明:
     1 Local<Integer> a = code.newLocal(TypeId.INT); 

    变量赋值:
     1 code.loadConstant(a, 0xabcd); 

    函数声明:
     1 MethodId<Integer, String> toHexString = TypeId.get(Integer.class).getMethod(TypeId.STRING, "toHexString", TypeId.INT); 

    函数调用:
     1 code.invokeStatic(toHexString, s, c); 

    过程非常简单,要生成一个完整的简单的类按照此步骤能很快完成。好的,现在进入正片部分了,即在Android平台使用dexmaker的情况。
    
    
  • 相关阅读:
    Redis 常用命令整理
    TCP系列01—概述及协议头格式
    TCP/IP详解--TCP网络传输数据包1460MSS和1448负载
    TCP中报文段大小(MSS)、MTU
    DNS 过滤脚本
    TCP SYN Cookies – DDoS defence
    python virtualenv venv 虚拟环境
    git 命令总结
    王兴三横四纵
    获取国税门户可供下载的资源文档
  • 原文地址:https://www.cnblogs.com/HaroldTihan/p/4607949.html
Copyright © 2020-2023  润新知