1*0c56280aSSorin Basca /* 2*0c56280aSSorin Basca * Licensed to the Apache Software Foundation (ASF) under one or more 3*0c56280aSSorin Basca * contributor license agreements. See the NOTICE file distributed with 4*0c56280aSSorin Basca * this work for additional information regarding copyright ownership. 5*0c56280aSSorin Basca * The ASF licenses this file to You under the Apache License, Version 2.0 6*0c56280aSSorin Basca * (the "License"); you may not use this file except in compliance with 7*0c56280aSSorin Basca * the License. You may obtain a copy of the License at 8*0c56280aSSorin Basca * 9*0c56280aSSorin Basca * http://www.apache.org/licenses/LICENSE-2.0 10*0c56280aSSorin Basca * 11*0c56280aSSorin Basca * Unless required by applicable law or agreed to in writing, software 12*0c56280aSSorin Basca * distributed under the License is distributed on an "AS IS" BASIS, 13*0c56280aSSorin Basca * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*0c56280aSSorin Basca * See the License for the specific language governing permissions and 15*0c56280aSSorin Basca * limitations under the License. 16*0c56280aSSorin Basca * 17*0c56280aSSorin Basca */ 18*0c56280aSSorin Basca 19*0c56280aSSorin Basca import java.io.IOException; 20*0c56280aSSorin Basca 21*0c56280aSSorin Basca import org.apache.bcel.Constants; 22*0c56280aSSorin Basca import org.apache.bcel.generic.ALOAD; 23*0c56280aSSorin Basca import org.apache.bcel.generic.ASTORE; 24*0c56280aSSorin Basca import org.apache.bcel.generic.ArrayType; 25*0c56280aSSorin Basca import org.apache.bcel.generic.ClassGen; 26*0c56280aSSorin Basca import org.apache.bcel.generic.ConstantPoolGen; 27*0c56280aSSorin Basca import org.apache.bcel.generic.GOTO; 28*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionConstants; 29*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionFactory; 30*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionHandle; 31*0c56280aSSorin Basca import org.apache.bcel.generic.InstructionList; 32*0c56280aSSorin Basca import org.apache.bcel.generic.LocalVariableGen; 33*0c56280aSSorin Basca import org.apache.bcel.generic.MethodGen; 34*0c56280aSSorin Basca import org.apache.bcel.generic.ObjectType; 35*0c56280aSSorin Basca import org.apache.bcel.generic.PUSH; 36*0c56280aSSorin Basca import org.apache.bcel.generic.Type; 37*0c56280aSSorin Basca 38*0c56280aSSorin Basca /** 39*0c56280aSSorin Basca * Create HelloWorld class: 40*0c56280aSSorin Basca * <PRE> 41*0c56280aSSorin Basca * import java.io.*; 42*0c56280aSSorin Basca * 43*0c56280aSSorin Basca * public class HelloWorld { 44*0c56280aSSorin Basca * public static void main(String[] argv) { 45*0c56280aSSorin Basca * BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 46*0c56280aSSorin Basca * String name = null; 47*0c56280aSSorin Basca * 48*0c56280aSSorin Basca * try { 49*0c56280aSSorin Basca * System.out.print("Please enter your name> "); 50*0c56280aSSorin Basca * name = in.readLine(); 51*0c56280aSSorin Basca * } catch(IOException e) { 52*0c56280aSSorin Basca * System.out.println(e); 53*0c56280aSSorin Basca * return; 54*0c56280aSSorin Basca * } 55*0c56280aSSorin Basca * 56*0c56280aSSorin Basca * System.out.println("Hello, " + name); 57*0c56280aSSorin Basca * } 58*0c56280aSSorin Basca * } 59*0c56280aSSorin Basca * </PRE> 60*0c56280aSSorin Basca * 61*0c56280aSSorin Basca * @version $Id$ 62*0c56280aSSorin Basca */ 63*0c56280aSSorin Basca public class HelloWorldBuilder { main(String[] argv)64*0c56280aSSorin Basca public static void main(String[] argv) { 65*0c56280aSSorin Basca ClassGen cg = new ClassGen("HelloWorld", "java.lang.Object", 66*0c56280aSSorin Basca "<generated>", Constants.ACC_PUBLIC | 67*0c56280aSSorin Basca Constants.ACC_SUPER, 68*0c56280aSSorin Basca null); 69*0c56280aSSorin Basca ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool 70*0c56280aSSorin Basca InstructionList il = new InstructionList(); 71*0c56280aSSorin Basca MethodGen mg = new MethodGen(Constants.ACC_STATIC | 72*0c56280aSSorin Basca Constants.ACC_PUBLIC,// access flags 73*0c56280aSSorin Basca Type.VOID, // return type 74*0c56280aSSorin Basca new Type[]{ // argument types 75*0c56280aSSorin Basca new ArrayType(Type.STRING, 1) 76*0c56280aSSorin Basca }, 77*0c56280aSSorin Basca new String[]{"argv"}, // arg names 78*0c56280aSSorin Basca "main", "HelloWorld", // method, class 79*0c56280aSSorin Basca il, cp); 80*0c56280aSSorin Basca InstructionFactory factory = new InstructionFactory(cg); 81*0c56280aSSorin Basca 82*0c56280aSSorin Basca ObjectType i_stream = new ObjectType("java.io.InputStream"); 83*0c56280aSSorin Basca ObjectType p_stream = new ObjectType("java.io.PrintStream"); 84*0c56280aSSorin Basca 85*0c56280aSSorin Basca // Create BufferedReader object and store it in local variable `in'. 86*0c56280aSSorin Basca il.append(factory.createNew("java.io.BufferedReader")); 87*0c56280aSSorin Basca il.append(InstructionConstants.DUP); // Use predefined constant, i.e. flyweight 88*0c56280aSSorin Basca il.append(factory.createNew("java.io.InputStreamReader")); 89*0c56280aSSorin Basca il.append(InstructionConstants.DUP); 90*0c56280aSSorin Basca il.append(factory.createFieldAccess("java.lang.System", "in", i_stream, Constants.GETSTATIC)); 91*0c56280aSSorin Basca 92*0c56280aSSorin Basca // Call constructors, i.e. BufferedReader(InputStreamReader()) 93*0c56280aSSorin Basca il.append(factory.createInvoke("java.io.InputStreamReader", "<init>", 94*0c56280aSSorin Basca Type.VOID, new Type[]{i_stream}, 95*0c56280aSSorin Basca Constants.INVOKESPECIAL)); 96*0c56280aSSorin Basca il.append(factory.createInvoke("java.io.BufferedReader", "<init>", Type.VOID, 97*0c56280aSSorin Basca new Type[]{new ObjectType("java.io.Reader")}, 98*0c56280aSSorin Basca Constants.INVOKESPECIAL)); 99*0c56280aSSorin Basca 100*0c56280aSSorin Basca // Create local variable `in' 101*0c56280aSSorin Basca LocalVariableGen lg = mg.addLocalVariable("in", new ObjectType("java.io.BufferedReader"), null, null); 102*0c56280aSSorin Basca int in = lg.getIndex(); 103*0c56280aSSorin Basca lg.setStart(il.append(new ASTORE(in))); // `i' valid from here 104*0c56280aSSorin Basca 105*0c56280aSSorin Basca // Create local variable `name' 106*0c56280aSSorin Basca lg = mg.addLocalVariable("name", Type.STRING, null, null); 107*0c56280aSSorin Basca int name = lg.getIndex(); 108*0c56280aSSorin Basca il.append(InstructionConstants.ACONST_NULL); 109*0c56280aSSorin Basca lg.setStart(il.append(new ASTORE(name))); // `name' valid from here 110*0c56280aSSorin Basca 111*0c56280aSSorin Basca // try { ... 112*0c56280aSSorin Basca InstructionHandle try_start = 113*0c56280aSSorin Basca il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC)); 114*0c56280aSSorin Basca 115*0c56280aSSorin Basca il.append(new PUSH(cp, "Please enter your name> ")); 116*0c56280aSSorin Basca il.append(factory.createInvoke("java.io.PrintStream", "print", Type.VOID, 117*0c56280aSSorin Basca new Type[]{Type.STRING}, Constants.INVOKEVIRTUAL)); 118*0c56280aSSorin Basca il.append(new ALOAD(in)); 119*0c56280aSSorin Basca il.append(factory.createInvoke("java.io.BufferedReader", "readLine", 120*0c56280aSSorin Basca Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); 121*0c56280aSSorin Basca il.append(new ASTORE(name)); 122*0c56280aSSorin Basca 123*0c56280aSSorin Basca // Upon normal execution we jump behind exception handler, the target address is not known yet. 124*0c56280aSSorin Basca GOTO g = new GOTO(null); 125*0c56280aSSorin Basca InstructionHandle try_end = il.append(g); 126*0c56280aSSorin Basca 127*0c56280aSSorin Basca /* } catch() { ... } 128*0c56280aSSorin Basca * Add exception handler: print exception and return from method 129*0c56280aSSorin Basca */ 130*0c56280aSSorin Basca InstructionHandle handler = 131*0c56280aSSorin Basca il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC)); 132*0c56280aSSorin Basca // Little trick in order not to save exception object temporarily 133*0c56280aSSorin Basca il.append(InstructionConstants.SWAP); 134*0c56280aSSorin Basca 135*0c56280aSSorin Basca il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[]{Type.OBJECT}, Constants.INVOKEVIRTUAL)); 136*0c56280aSSorin Basca il.append(InstructionConstants.RETURN); 137*0c56280aSSorin Basca mg.addExceptionHandler(try_start, try_end, handler, new ObjectType("java.io.IOException")); 138*0c56280aSSorin Basca 139*0c56280aSSorin Basca // Normal code continues, now we can set the branch target of the GOTO that jumps over the handler code. 140*0c56280aSSorin Basca InstructionHandle ih = 141*0c56280aSSorin Basca il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC)); 142*0c56280aSSorin Basca g.setTarget(ih); 143*0c56280aSSorin Basca 144*0c56280aSSorin Basca // String concatenation compiles to StringBuffer operations. 145*0c56280aSSorin Basca il.append(factory.createNew(Type.STRINGBUFFER)); 146*0c56280aSSorin Basca il.append(InstructionConstants.DUP); 147*0c56280aSSorin Basca il.append(new PUSH(cp, "Hello, ")); 148*0c56280aSSorin Basca il.append(factory.createInvoke("java.lang.StringBuffer", "<init>", 149*0c56280aSSorin Basca Type.VOID, new Type[]{Type.STRING}, 150*0c56280aSSorin Basca Constants.INVOKESPECIAL)); 151*0c56280aSSorin Basca il.append(new ALOAD(name)); 152*0c56280aSSorin Basca 153*0c56280aSSorin Basca // Concatenate strings using a StringBuffer and print them. 154*0c56280aSSorin Basca il.append(factory.createInvoke("java.lang.StringBuffer", "append", 155*0c56280aSSorin Basca Type.STRINGBUFFER, new Type[]{Type.STRING}, 156*0c56280aSSorin Basca Constants.INVOKEVIRTUAL)); 157*0c56280aSSorin Basca il.append(factory.createInvoke("java.lang.StringBuffer", "toString", 158*0c56280aSSorin Basca Type.STRING, Type.NO_ARGS, 159*0c56280aSSorin Basca Constants.INVOKEVIRTUAL)); 160*0c56280aSSorin Basca 161*0c56280aSSorin Basca il.append(factory.createInvoke("java.io.PrintStream", "println", 162*0c56280aSSorin Basca Type.VOID, new Type[]{Type.STRING}, 163*0c56280aSSorin Basca Constants.INVOKEVIRTUAL)); 164*0c56280aSSorin Basca 165*0c56280aSSorin Basca il.append(InstructionConstants.RETURN); 166*0c56280aSSorin Basca 167*0c56280aSSorin Basca mg.setMaxStack(5); // Needed stack size 168*0c56280aSSorin Basca cg.addMethod(mg.getMethod()); 169*0c56280aSSorin Basca 170*0c56280aSSorin Basca il.dispose(); // Reuse instruction handles 171*0c56280aSSorin Basca 172*0c56280aSSorin Basca // Add public <init> method, i.e. empty constructor 173*0c56280aSSorin Basca cg.addEmptyConstructor(Constants.ACC_PUBLIC); 174*0c56280aSSorin Basca 175*0c56280aSSorin Basca // Get JavaClass object and dump it to file. 176*0c56280aSSorin Basca try { 177*0c56280aSSorin Basca cg.getJavaClass().dump("HelloWorld.class"); 178*0c56280aSSorin Basca } catch (IOException e) { 179*0c56280aSSorin Basca System.err.println(e); 180*0c56280aSSorin Basca } 181*0c56280aSSorin Basca } 182*0c56280aSSorin Basca } 183