標籤:
一、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使用