1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dx.examples; 18 19 import com.android.dx.Code; 20 import com.android.dx.FieldId; 21 import com.android.dx.Local; 22 import com.android.dx.TypeId; 23 import com.android.dx.BinaryOp; 24 import com.android.dx.DexMaker; 25 import com.android.dx.MethodId; 26 27 import java.io.File; 28 import java.io.PrintStream; 29 import java.lang.reflect.Modifier; 30 31 public final class HelloWorldMaker { 32 public static void main(String[] args) throws Exception { 33 DexMaker dexMaker = new DexMaker(); 34 35 // Generate a HelloWorld class. 36 TypeId<?> helloWorld = TypeId.get("LHelloWorld;"); 37 dexMaker.declare(helloWorld, "HelloWorld.generated", Modifier.PUBLIC, TypeId.OBJECT); 38 generateHelloMethod(dexMaker, helloWorld); 39 40 // Create the dex file and load it. 41 File outputDir = new File("."); 42 ClassLoader loader = dexMaker.generateAndLoad(HelloWorldMaker.class.getClassLoader(), 43 outputDir); 44 Class<?> helloWorldClass = loader.loadClass("HelloWorld"); 45 46 // Execute our newly-generated code in-process. 47 helloWorldClass.getMethod("hello").invoke(null); 48 } 49 50 /** 51 * Generates Dalvik bytecode equivalent to the following method. 52 * public static void hello() { 53 * int a = 0xabcd; 54 * int b = 0xaaaa; 55 * int c = a - b; 56 * String s = Integer.toHexString(c); 57 * System.out.println(s); 58 * return; 59 * } 60 */ 61 private static void generateHelloMethod(DexMaker dexMaker, TypeId<?> declaringType) { 62 // Lookup some types we'll need along the way. 63 TypeId<System> systemType = TypeId.get(System.class); 64 TypeId<PrintStream> printStreamType = TypeId.get(PrintStream.class); 65 66 // Identify the 'hello()' method on declaringType. 67 MethodId hello = declaringType.getMethod(TypeId.VOID, "hello"); 68 69 // Declare that method on the dexMaker. Use the returned Code instance 70 // as a builder that we can append instructions to. 71 Code code = dexMaker.declare(hello, Modifier.STATIC | Modifier.PUBLIC); 72 73 // Declare all the locals we'll need up front. The API requires this. 74 Local<Integer> a = code.newLocal(TypeId.INT); 75 Local<Integer> b = code.newLocal(TypeId.INT); 76 Local<Integer> c = code.newLocal(TypeId.INT); 77 Local<String> s = code.newLocal(TypeId.STRING); 78 Local<PrintStream> localSystemOut = code.newLocal(printStreamType); 79 80 // int a = 0xabcd; 81 code.loadConstant(a, 0xabcd); 82 83 // int b = 0xaaaa; 84 code.loadConstant(b, 0xaaaa); 85 86 // int c = a - b; 87 code.op(BinaryOp.SUBTRACT, c, a, b); 88 89 // String s = Integer.toHexString(c); 90 MethodId<Integer, String> toHexString 91 = TypeId.get(Integer.class).getMethod(TypeId.STRING, "toHexString", TypeId.INT); 92 code.invokeStatic(toHexString, s, c); 93 94 // System.out.println(s); 95 FieldId<System, PrintStream> systemOutField = systemType.getField(printStreamType, "out"); 96 code.sget(systemOutField, localSystemOut); 97 MethodId<PrintStream, Void> printlnMethod = printStreamType.getMethod( 98 TypeId.VOID, "println", TypeId.STRING); 99 code.invokeVirtual(printlnMethod, null, localSystemOut, s); 100 101 // return; 102 code.returnVoid(); 103 } 104 }