Home | History | Annotate | Download | only in examples
      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 }