📄 appendix.tex
字号:
\section{Code examples for the BCEL API}\label{sec:apicg}\subsection{HelloWorldBuilder.java}The following Java program reads a name from the standard input andprints a friendly ``Hello''. Since the \texttt{readLine()} method maythrow an \texttt{IOException} it is enclosed by a \texttt{try-catch} block.{\small \verbatimtabinput{HelloWorld.java}\label{sec:hello}}\subsection{HelloWorldBuilder.java}We will sketch here how the above Java class can be created from thescratch using the \jc API. For ease of reading we willuse textual signatures and not create them dynamically. For example,the signature\begin{verbatim} "(Ljava/lang/String;)Ljava/lang/StringBuffer;"\end{verbatim}would actually be created with\begin{verbatim} Type.getMethodSignature(Type.STRINGBUFFER, new Type[] { Type.STRING });\end{verbatim}\subsubsection{Initialization:}First we create an empty class and an instruction list:{\small\begin{verbatim} ClassGen cg = new ClassGen("HelloWorld", "java.lang.Object", "<generated>", ACC_PUBLIC | ACC_SUPER, null); ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool InstructionList il = new InstructionList();\end{verbatim}}We then create the main method, supplying the method's name and thesymbolic type signature encoded with \texttt{Type} objects.{\small\begin{verbatim} 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);\end{verbatim}}We define some often used types:{\small\begin{verbatim} ObjectType i_stream = new ObjectType("java.io.InputStream"); ObjectType p_stream = new ObjectType("java.io.PrintStream");\end{verbatim}}\subsubsection{Create variables \texttt{in} and \texttt{name}:}We call the constructors, i.e. execute\texttt{BufferedReader(Input\-Stream\-Reader(System.in))}. The referenceto the \texttt{BufferedReader} object stays on top of the stack and isstored in the newly allocated \texttt{in} variable.{\small\begin{verbatim} 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", "<init>", Type.VOID, new Type[] { i_stream }, Constants.INVOKESPECIAL)); il.append(factory.createInvoke("java.io.BufferedReader", "<init>", 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\end{verbatim}}Create local variable \texttt{name} and initialize it to \texttt{null}.{\small\begin{verbatim} 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\end{verbatim}}\subsubsection{Create try-catch block}We remember the start of the block, read a line from the standardinput and store it into the variable \texttt{name}.{\small\begin{verbatim} InstructionHandle try_start = il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC)); il.append(new PUSH(cp, "Please enter your name> ")); 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));\end{verbatim}}Upon normal execution we jump behind exception handler, the targetaddress is not known yet.{\small\begin{verbatim} GOTO g = new GOTO(null); InstructionHandle try_end = il.append(g);\end{verbatim}}We add the exception handler which simply returns from the method.{\small\begin{verbatim} InstructionHandle handler = il.append(InstructionConstants.RETURN); mg.addExceptionHandler(try_start, try_end, handler, "java.io.IOException");\end{verbatim}}``Normal'' code continues, now we can set the branch target of the GOTO.{\small\begin{verbatim} InstructionHandle ih = il.append(factory.createFieldAccess("java.lang.System", "out", p_stream, Constants.GETSTATIC)); g.setTarget(ih);\end{verbatim}}\subsubsection{Printing "Hello"}String concatenation compiles to \texttt{StringBuffer} operations.{\small\begin{verbatim} il.append(factory.createNew(Type.STRINGBUFFER)); il.append(InstructionConstants.DUP); il.append(new PUSH(cp, "Hello, ")); il.append(factory.createInvoke("java.lang.StringBuffer", "<init>", 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);\end{verbatim}}\subsubsection{Finalization}Finally, we have to set the stack size, which normally would becomputed on the fly and add a default constructor method to the class,which is empty in this case.{\small\begin{verbatim} mg.setMaxStack(5); cg.addMethod(mg.getMethod()); il.dispose(); // Allow instruction handles to be reused cg.addEmptyConstructor(ACC_PUBLIC);\end{verbatim}}Last but not least we dump the \texttt{JavaClass} object to a file.{\small\begin{verbatim} try { cg.getJavaClass().dump("HelloWorld.class"); } catch(java.io.IOException e) { System.err.println(e); }\end{verbatim}}\subsection{Peephole.java}This class implements a simple peephole optimizer that removes any NOPinstructions from the given class.{\small\verbatimtabinput{Peephole.java}}\label{sec:nop}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -