📄 manual.tex
字号:
null); MethodGen mg = new MethodGen(ACC_STATIC | ACC_PUBLIC, Type.VOID, new Type[] { new ArrayType(Type.STRING, 1) }, new String[] { "argv" }, "main", "HelloWorld", il, cp); ... cg.addMethod(mg.getMethod()); il.dispose(); // Reuse instruction handles of list\end{verbatim}\subsubsection{Code example revisited}Using instruction lists gives us a generic view upon the code: InFigure \ref{fig:il} we again present the code chunk of the\texttt{readInt()} method of the faculty example in section\ref{sec:fac}: The local variables \texttt{n} and \texttt{e1} bothhold two references to instructions, defining their scope. There aretwo \texttt{goto}s branching to the \texttt{iload} at the end of themethod. One of the exception handlers is displayed, too: it referencesthe start and the end of the \texttt{try} block and also the exceptionhandler code.\begin{figure}[htbp] \begin{center} \leavevmode \epsfxsize\textwidth \epsfbox{eps/il.eps} \caption{Instruction list for \texttt{readInt()} method} \label{fig:il} \end{center}\end{figure}\subsubsection{Instruction factories}\label{sec:compound}To simplify the creation of certain instructions the user can use thesupplied \texttt{InstructionFactory} class which offers a lot ofuseful methods to create instructions from scratch. Alternatively, hecan also use \emph{compound instructions}: When producing byte code,some patterns typically occur very frequently, for instance thecompilation of arithmetic or comparison expressions. You certainly donot want to rewrite the code that translates such expressions intobyte code in every place they may appear. In order to support this,the \jc API includes a \emph{compound instruction} (an interface witha single \texttt{getInstructionList()} method). Instances of thisclass may be used in any place where normal instructions would occur,particularly in append operations.\paragraph{Example: Pushing constants.}Pushing constants onto the operand stack may be coded in differentways. As explained in section \ref{sec:code} there are some``short-cut'' instructions that can be used to make the produced bytecode more compact. The smallest instruction to push a single\texttt{1} onto the stack is \texttt{iconst\_1}, other possibilitiesare \texttt{bipush} (can be used to push values between -128 and 127),\texttt{sipush} (between -32768 and 32767), or \texttt{ldc} (loadconstant from \cpe).Instead of repeatedly selecting the most compact instruction in, say,a switch, one can use the compound \texttt{PUSH} instruction wheneverpushing a constant number or string. It will produce the appropriatebyte code instruction and insert entries into to \cp if necessary.\begin{verbatim} il.append(new PUSH(cp, "Hello, world")); il.append(new PUSH(cp, 4711));\end{verbatim}\subsubsection{Code patterns using regular expressions}\label{sec:peephole}When transforming code, for instance during optimization or wheninserting analysis method calls, one typically searches for certainpatterns of code to perform the transformation at. To simplifyhandling such situations \jc introduces a special feature: One cansearch for given code patterns within an instruction list using\emph{regular expressions}. In such expressions, instructions arerepresented by symbolic names, e.g. "\texttt{`IfInstruction'}". Metacharacters like \verb|+|, \verb|*|, and \verb@(..|..)@ have theirusual meanings. Thus, the expression\begin{verbatim} "`NOP'+(`ILOAD__'|`ALOAD__')*"\end{verbatim}represents a piece of code consisting of at least one \texttt{NOP}followed by a possibly empty sequence of \texttt{ILOAD} and\texttt{ALOAD} instructions.The \texttt{search()} method of class \texttt{FindPattern} gets aninstruction list and a regular expression as arguments and returns anarray describing the area of matched instructions. Additionalconstraints to the matching area of instructions, which can not beimplemented via regular expressions, may be expressed via \emph{codeconstraints}.\subsubsection{Example: Optimizing boolean expressions.}In Java, boolean values are mapped to 1 and to 0, respectively. Thus,the simplest way to evaluate boolean expressions is to push a 1 or a 0onto the operand stack depending on the truth value of the expression.But this way, the subsequent combination of boolean expressions (with\verb|&&|, e.g) yields long chunks of code that push lots of 1s and0s onto the stack.When the code has been finalized these chunks can be optimized with a\emph{peep hole} algorithm: An \texttt{IfInstruction} (e.g. thecomparison of two integers: \texttt{if\_icmpeq}) that either producesa 1 or a 0 on the stack and is followed by an \texttt{ifne}instruction (branch if stack value $\neq$ 0) may be replaced by the\texttt{IfInstruction} with its branch target replaced by the targetof the \texttt{ifne} instruction:{\small \verbatimtabinput{bool.java}}The applied code constraint object ensures that the matched codereally corresponds to the targeted expression pattern. Subsequentapplication of this algorithm removes all unnecessary stack operationsand branch instructions from the byte code. If any of the deletedinstructions is still referenced by an \texttt{InstructionTargeter}object, the reference has to be updated in the \texttt{catch}-clause.Code example \ref{sec:hello} gives a verbose example of how to createa class file, while example \ref{sec:nop} shows how to implement asimple peephole optimizer and how to deal with \texttt{TargetLost}exceptions.\paragraph{Example application:}The expression\begin{verbatim} if((a == null) || (i < 2)) System.out.println("Ooops");\end{verbatim}can be mapped to both of the chunks of byte code shown in figure\ref{fig:code}. The left column represents the unoptimized code whilethe right column displays the same code after an aggressivelyoptimizing peep hole algorithm has been applied:\begin{figure}[hpt]\begin{minipage}{0.49\textwidth} {\small \verbatimtabinput{unopt}} \vfil\end{minipage}\begin{minipage}{0.49\textwidth} {\small \verbatimtabinput{opt}} \vfil\end{minipage}\label{fig:code}\caption{Optimizing boolean expressions}\begin{center} \end{center}\end{figure}\section{Application areas}\label{sec:application}There are many possible application areas for \jc ranging from classbrowsers, profilers, byte code optimizers, and compilers tosophisticated run-time analysis tools and extensions to the Javalanguage \cite{agesen, myers}.Compilers like the Barat compiler \cite{barat} use \jc to implement abyte code generating back end. Other possible application areas arethe static analysis of byte code \cite{thies} or examining therun-time behavior of classes by inserting calls to profiling methodsinto the code. Further examples are extending Java with Eiffel-likeassertions \cite{jawa}, automated delegation \cite{classfilters}, orwith the concepts of ``Aspect-Oriented Programming'' \cite{aspect}.\subsection{Class loaders}\label{sec:classloaders}Class loaders are responsible for loading class files from the filesystem or other resources and passing the byte code to the \vm\cite{classloader}. A custom \texttt{ClassLoader} object may be usedto intercept the standard procedure of loading a class, i.e. thesystem class loader, and perform some transformations before actuallypassing the byte code to the JVM.A possible scenario is described in figure \ref{fig:classloader}:During run-time the \vm requests a custom class loader to load a givenclass. But before the JVM actually sees the byte code, the classloader makes a ``side-step'' and performs some transformation to theclass. To make sure that the modified byte code is still valid anddoes not violate any of the JVM's rules it is checked by the verifierbefore the JVM finally executes it.\begin{figure}[ht] \begin{center} \leavevmode \epsfxsize\textwidth \epsfbox{eps/classloader.eps} \caption{Class loaders}\label{fig:classloader} \end{center}\end{figure}Using class loaders is an elegant way of extending the \jvm with newfeatures without actually modifying it. This concept enablesdevelopers to use \emph{load-time reflection} to implement their ideasas opposed to the static reflection supported by the Java ReflectionAPI \cite{reflection}. Load-time transformations supply the user witha new level of abstraction. He is not strictly tied to the staticconstraints of the original authors of the classes but may customizethe applications with third-party code in order to benefit from newfeatures. Such transformations may be executed on demand and neitherinterfere with other users, nor alter the original byte code. In fact,class loaders may even create classes \emph{ad hoc} without loading afile at all.\subsubsection{Example: Poor Man's Genericity}The ``Poor Man's Genericity'' project \cite{pmg} that extends Javawith parameterized classes, for example, uses \jc in two places togenerate instances of parameterized classes: During compile-time (thestandard \texttt{javac} with some slightly changed classes) and atrun-time using a custom class loader. The compiler puts someadditional type information into class files which is evaluated atload-time by the class loader. The class loader performs sometransformations on the loaded class and passes them to the VM. Thefollowing algorithm illustrates how the load method of the classloader fulfills the request for a parameterized class,e.g. \verb|Stack<String>|\begin{enumerate}\item Search for class \texttt{Stack}, load it, and check for acertain class attribute containing additional type information. I.e.the attribute defines the ``real'' name of the class,i.e. \verb|Stack<A>|.\item Replace all occurrences and references to the formal type\texttt{A} with references to the actual type \texttt{String}. Forexample the method\begin{verbatim} void push(A obj) { ... }\end{verbatim}becomes\begin{verbatim} void push(String obj) { ... }\end{verbatim}\item Return the resulting class to the Virtual Machine.\end{enumerate}\bibliographystyle{alpha}\bibliography{manual}\newpage\appendix\pagestyle{empty}\include{appendix}\include{diagrams}\end{document}% LocalWords: Freie Universit Institut Informatik dahm inf fu berlin de JOIE% LocalWords: JCF HelloWorld Jasmin Eiffel SourceFile classfile lang io ldc ar% LocalWords: PrintStream invokevirtual MethodRef ConstantClass Fieldref dup% LocalWords: iconst bipush iadd cmpeq jsr athrow iload istore iastore er ic% LocalWords: getfield putfield getstatic putstatic invokestatic newarray nop% LocalWords: anewarray checkcast instanceof lookupswitch tableswitch Barat VM% LocalWords: ConstantPool getConstant LineNumberTable LocalvariableTable ifne% LocalWords: invokesta invokespecial multianewarray ConstantPoolGen MethodGen% LocalWords: BasicType ObjectType ArrayType InstructionTarge getByteCode bool% LocalWords: BranchInstruction InstructionTargeter InstructionHandle regex% LocalWords: TargetLostException codeconstraint CompoundInstruction sipush% LocalWords: getInstructionList FindPattern CodeConstraint IfInstruction fac% LocalWords: TargetLost javac readLine IOException parseInt readInt CLASSPATH% LocalWords: NumberFormatException toString JasminVisitor getSignature JVM's% LocalWords: FieldGen updateTarget LGPL BCEL LocalVariableTable setMaxStack% LocalWords: setMaxLocals InstructionConstants TypedInstruction addAttribute% LocalWords: ExceptionThrower getMethod InstructionFactory ALOAD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -