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 17package com.google.dexmaker.examples; 18 19import com.google.dexmaker.BinaryOp; 20import com.google.dexmaker.Code; 21import com.google.dexmaker.DexMaker; 22import com.google.dexmaker.FieldId; 23import com.google.dexmaker.Local; 24import com.google.dexmaker.MethodId; 25import com.google.dexmaker.TypeId; 26import java.io.File; 27import java.io.PrintStream; 28import java.lang.reflect.Modifier; 29 30public final class HelloWorldMaker { 31 public static void main(String[] args) throws Exception { 32 DexMaker dexMaker = new DexMaker(); 33 34 // Generate a HelloWorld class. 35 TypeId<?> helloWorld = TypeId.get("LHelloWorld;"); 36 dexMaker.declare(helloWorld, "HelloWorld.generated", Modifier.PUBLIC, TypeId.OBJECT); 37 generateHelloMethod(dexMaker, helloWorld); 38 39 // Create the dex file and load it. 40 File outputDir = new File("."); 41 ClassLoader loader = dexMaker.generateAndLoad(HelloWorldMaker.class.getClassLoader(), 42 outputDir); 43 Class<?> helloWorldClass = loader.loadClass("HelloWorld"); 44 45 // Execute our newly-generated code in-process. 46 helloWorldClass.getMethod("hello").invoke(null); 47 } 48 49 /** 50 * Generates Dalvik bytecode equivalent to the following method. 51 * public static void hello() { 52 * int a = 0xabcd; 53 * int b = 0xaaaa; 54 * int c = a - b; 55 * String s = Integer.toHexString(c); 56 * System.out.println(s); 57 * return; 58 * } 59 */ 60 private static void generateHelloMethod(DexMaker dexMaker, TypeId<?> declaringType) { 61 // Lookup some types we'll need along the way. 62 TypeId<System> systemType = TypeId.get(System.class); 63 TypeId<PrintStream> printStreamType = TypeId.get(PrintStream.class); 64 65 // Identify the 'hello()' method on declaringType. 66 MethodId hello = declaringType.getMethod(TypeId.VOID, "hello"); 67 68 // Declare that method on the dexMaker. Use the returned Code instance 69 // as a builder that we can append instructions to. 70 Code code = dexMaker.declare(hello, Modifier.STATIC | Modifier.PUBLIC); 71 72 // Declare all the locals we'll need up front. The API requires this. 73 Local<Integer> a = code.newLocal(TypeId.INT); 74 Local<Integer> b = code.newLocal(TypeId.INT); 75 Local<Integer> c = code.newLocal(TypeId.INT); 76 Local<String> s = code.newLocal(TypeId.STRING); 77 Local<PrintStream> localSystemOut = code.newLocal(printStreamType); 78 79 // int a = 0xabcd; 80 code.loadConstant(a, 0xabcd); 81 82 // int b = 0xaaaa; 83 code.loadConstant(b, 0xaaaa); 84 85 // int c = a - b; 86 code.op(BinaryOp.SUBTRACT, c, a, b); 87 88 // String s = Integer.toHexString(c); 89 MethodId<Integer, String> toHexString 90 = TypeId.get(Integer.class).getMethod(TypeId.STRING, "toHexString", TypeId.INT); 91 code.invokeStatic(toHexString, s, c); 92 93 // System.out.println(s); 94 FieldId<System, PrintStream> systemOutField = systemType.getField(printStreamType, "out"); 95 code.sget(systemOutField, localSystemOut); 96 MethodId<PrintStream, Void> printlnMethod = printStreamType.getMethod( 97 TypeId.VOID, "println", TypeId.STRING); 98 code.invokeVirtual(printlnMethod, null, localSystemOut, s); 99 100 // return; 101 code.returnVoid(); 102 } 103}