<?xml version="1.0"?>
<!--
    * Licensed to the Apache Software Foundation (ASF) under one
    * or more contributor license agreements.  See the NOTICE file
    * distributed with this work for additional information
    * regarding copyright ownership.  The ASF licenses this file
    * to you under the Apache License, Version 2.0 (the
    * "License"); you may not use this file except in compliance
    * with the License.  You may obtain a copy of the License at
    *
    *   http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing,
    * software distributed under the License is distributed on an
    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    * KIND, either express or implied.  See the License for the
    * specific language governing permissions and limitations
    * under the License.
-->
<document>
  <properties>
    <title>Appendix</title>
  </properties>

  <body>
    <section name="Appendix">

    <subsection name="HelloWorldBuilder">
      <p>
        The following program reads a name from the standard input and
        prints a friendly "Hello". Since the <tt>readLine()</tt> method may
        throw an <tt>IOException</tt> it is enclosed by a <tt>try-catch</tt>
        clause.
      </p>

      <source>
import java.io.*;

public class HelloWorld {
    public static void main(String[] argv) {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String name = null;

        try {
            System.out.print("Please enter your name&gt; ");
            name = in.readLine();
        } catch (IOException e) {
            return;
        }

        System.out.println("Hello, " + name);
    }
}
      </source>

      <p>
        We will sketch here how the above Java class can be created from the
        scratch using the <font face="helvetica,arial">BCEL</font> API. For
        ease of reading we will use textual signatures and not create them
        dynamically. For example, the signature
      </p>

      <source>"(Ljava/lang/String;)Ljava/lang/StringBuffer;"</source>

      <p>
        actually be created with
      </p>

      <source>Type.getMethodSignature(Type.STRINGBUFFER, new Type[] { Type.STRING });</source>

      <p><b>Initialization:</b>
        First we create an empty class and an instruction list:
      </p>

      <source>
ClassGen cg = new ClassGen("HelloWorld", "java.lang.Object",
                            "&lt;generated&gt;", ACC_PUBLIC | ACC_SUPER, null);
ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool
InstructionList il = new InstructionList();
      </source>

      <p>
        We then create the main method, supplying the method's name and the
        symbolic type signature encoded with <tt>Type</tt> objects.
      </p>

      <source>
MethodGen  mg = new MethodGen(ACC_STATIC | ACC_PUBLIC, // access flags
                              Type.VOID,               // return type
                              new Type[] {             // argument types
                              new ArrayType(Type.STRING, 1) },
                              new String[] { "argv" }, // arg names
                              "main", "HelloWorld",    // method, class
                              il, cp);
InstructionFactory factory = new InstructionFactory(cg);
      </source>

      <p>
        We now define some often used types:
      </p>

      <source>
ObjectType i_stream = new ObjectType("java.io.InputStream");
ObjectType p_stream = new ObjectType("java.io.PrintStream");
      </source>

      <p><b>Create variables <tt>in</tt> and <tt>name</tt>:</b> We call
        the constructors, i.e., execute
        <tt>BufferedReader(InputStreamReader(System.in))</tt>. The reference
        to the <tt>BufferedReader</tt> object stays on top of the stack and
        is stored in the newly allocated <tt>in</tt> variable.
      </p>

      <source>
il.append(factory.createNew("java.io.BufferedReader"));
il.append(InstructionConstants.DUP); // Use predefined constant
il.append(factory.createNew("java.io.InputStreamReader"));
il.append(InstructionConstants.DUP);
il.append(factory.createFieldAccess("java.lang.System", "in", i_stream, Constants.GETSTATIC));
il.append(factory.createInvoke("java.io.InputStreamReader", "&lt;init&gt;",
                                Type.VOID, new Type[] { i_stream },
                                Constants.INVOKESPECIAL));
il.append(factory.createInvoke("java.io.BufferedReader", "&lt;init&gt;", Type.VOID,
                                new Type[] {new ObjectType("java.io.Reader")},
                                Constants.INVOKESPECIAL));

LocalVariableGen lg = mg.addLocalVariable("in",
                        new ObjectType("java.io.BufferedReader"), null, null);
int in = lg.getIndex();
lg.setStart(il.append(new ASTORE(in))); // "i" valid from here
      </source>

      <p>
        Create local variable <tt>name</tt> and  initialize it to <tt>null</tt>.
      </p>

      <source>
lg = mg.addLocalVariable("name", Type.STRING, null, null);
int name = lg.getIndex();
il.append(InstructionConstants.ACONST_NULL);
lg.setStart(il.append(new ASTORE(name))); // "name" valid from here
      </source>

      <p><b>Create try-catch block:</b> We remember the start of the
        block, read a line from the standard input and store it into the
        variable <tt>name</tt>.
      </p>

      <source>
InstructionHandle try_start =
  il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC));

il.append(new PUSH(cp, "Please enter your name&gt; "));
il.append(factory.createInvoke("java.io.PrintStream", "print", Type.VOID,
                                new Type[] { Type.STRING },
                                Constants.INVOKEVIRTUAL));
il.append(new ALOAD(in));
il.append(factory.createInvoke("java.io.BufferedReader", "readLine",
                                Type.STRING, Type.NO_ARGS,
                                Constants.INVOKEVIRTUAL));
il.append(new ASTORE(name));
      </source>

      <p>
        Upon normal execution we jump behind exception handler, the target
        address is not known yet.
      </p>

      <source>
GOTO g = new GOTO(null);
InstructionHandle try_end = il.append(g);
      </source>

      <p>
        We add the exception handler which simply returns from the method.
      </p>

      <source>
InstructionHandle handler = il.append(InstructionConstants.RETURN);
mg.addExceptionHandler(try_start, try_end, handler, "java.io.IOException");
      </source>

      <p>
        "Normal" code continues, now we can set the branch target of the <tt>GOTO</tt>.
      </p>

      <source>
InstructionHandle ih =
  il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC));
g.setTarget(ih);
      </source>

      <p><b>Printing "Hello":</b>
String concatenation compiles to <tt>StringBuffer</tt> operations.
      </p>

      <source>
il.append(factory.createNew(Type.STRINGBUFFER));
il.append(InstructionConstants.DUP);
il.append(new PUSH(cp, "Hello, "));
il.append(factory.createInvoke("java.lang.StringBuffer", "&lt;init&gt;",
                                Type.VOID, new Type[] { Type.STRING },
                                Constants.INVOKESPECIAL));
il.append(new ALOAD(name));
il.append(factory.createInvoke("java.lang.StringBuffer", "append",
                                Type.STRINGBUFFER, new Type[] { Type.STRING },
                                Constants.INVOKEVIRTUAL));
il.append(factory.createInvoke("java.lang.StringBuffer", "toString",
                                Type.STRING, Type.NO_ARGS,
                                Constants.INVOKEVIRTUAL));

il.append(factory.createInvoke("java.io.PrintStream", "println",
                                Type.VOID, new Type[] { Type.STRING },
                                Constants.INVOKEVIRTUAL));
il.append(InstructionConstants.RETURN);
      </source>


      <p><b>Finalization:</b> Finally, we have to set the stack size,
        which normally would have to be computed on the fly and add a
        default constructor method to the class, which is empty in this
        case.
      </p>

      <source>
mg.setMaxStack();
cg.addMethod(mg.getMethod());
il.dispose(); // Allow instruction handles to be reused
cg.addEmptyConstructor(ACC_PUBLIC);
      </source>

      <p>
        Last but not least we dump the <tt>JavaClass</tt> object to a file.
      </p>

      <source>
try {
    cg.getJavaClass().dump("HelloWorld.class");
} catch (IOException e) {
    System.err.println(e);
}
      </source>

    </subsection>

    <subsection name="Peephole optimizer">
      <p>
        This class implements a simple peephole optimizer that removes any NOP
        instructions from the given class.
      </p>

      <source>
import java.io.*;

import java.util.Iterator;
import org.apache.bcel.classfile.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.Repository;
import org.apache.bcel.util.InstructionFinder;

public class Peephole {

    public static void main(String[] argv) {
        try {
            // Load the class from CLASSPATH.
            JavaClass clazz  = Repository.lookupClass(argv[0]);
            Method[] methods = clazz.getMethods();
            ConstantPoolGen cp = new ConstantPoolGen(clazz.getConstantPool());

            for (int i = 0; i &lt; methods.length; i++) {
                if (!(methods[i].isAbstract() || methods[i].isNative())) {
                    MethodGen mg = new MethodGen(methods[i], clazz.getClassName(), cp);
                    Method stripped = removeNOPs(mg);

                    if (stripped != null)      // Any NOPs stripped?
                        methods[i] = stripped; // Overwrite with stripped method
                  }
            }

            // Dump the class to "class name"_.class
            clazz.setConstantPool(cp.getFinalConstantPool());
            clazz.dump(clazz.getClassName() + "_.class");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Method removeNOPs(MethodGen mg) {
        InstructionList il = mg.getInstructionList();
        InstructionFinder f = new InstructionFinder(il);
        String pat = "NOP+"; // Find at least one NOP
        InstructionHandle next = null;
        int count = 0;

        for (Iterator iter = f.search(pat); iter.hasNext();) {
            InstructionHandle[] match = (InstructionHandle[]) iter.next();
            InstructionHandle first = match[0];
            InstructionHandle last  = match[match.length - 1];

            // Some nasty Java compilers may add NOP at end of method.
            if ((next = last.getNext()) == null) {
                break;
            }

            count += match.length;

            /**
             * Delete NOPs and redirect any references to them to the following (non-nop) instruction.
             */
            try {
                il.delete(first, last);
            } catch (TargetLostException e) {
                for (InstructionHandle target : e.getTargets()) {
                    for (InstructionTargeter targeter = target.getTargeters()) {
                        targeter.updateTarget(target, next);
                    }
                }
            }
        }

        Method m = null;

        if (count &gt; 0) {
            System.out.println("Removed " + count + " NOP instructions from method " + mg.getName());
            m = mg.getMethod();
        }

        il.dispose(); // Reuse instruction handles
        return m;
    }
}
      </source>
    </subsection>

    <subsection name="BCELifier">
      <p>
        If you want to learn how certain things are generated using BCEL you
        can do the following: Write your program with the needed features in
        Java and compile it as usual. Then use <tt>BCELifier</tt> to create
        a class that creates that very input class using BCEL.<br/>
        (Think about this sentence for a while, or just try it ...)
      </p>
    </subsection>

    <subsection name="Constant pool UML diagram">

      <p align="center">
        <a name="Figure 8">
          <img src="../images/constantpool.gif"/>
          <br/>
          Figure 8: UML diagram for constant pool classes
        </a>
      </p>
    </subsection>

    <subsection name="Verifier">

      <h4>Running a console based verifier</h4>

      <source>
java org.apache.bcel.verifier.Verifier fully.qualified.class.Name
      </source>

      lets JustIce work standalone.
      If you get a "java.lang.OutOfMemoryError", you should increase the
      maximum Java heap space. A command like

      <source>
java -Xmx1887436800 org.apache.bcel.verifier.Verifier f.q.c.Name
      </source>

      will usually resolve the problem. The value above is suitable for
      big server machines; if your machine starts swapping to disk, try
      to lower the value.

      <h4>Running a graphics based verifier</h4>

      If you prefer a graphical application, you should use a command like

      <source>
java org.apache.bcel.verifier.GraphicalVerifier
      </source>

      to launch one. Again, you may have to resolve a memory issue depending
      on the classes to verify.
    </subsection>
  </section>
  </body>
</document>
