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.google.dexmaker.examples;
     18 
     19 import com.google.dexmaker.BinaryOp;
     20 import com.google.dexmaker.Code;
     21 import com.google.dexmaker.DexMaker;
     22 import com.google.dexmaker.FieldId;
     23 import com.google.dexmaker.Local;
     24 import com.google.dexmaker.MethodId;
     25 import com.google.dexmaker.TypeId;
     26 import java.io.File;
     27 import java.io.PrintStream;
     28 import java.lang.reflect.Modifier;
     29 
     30 public 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 }