123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <title>Javassist Tutorial</title>
- <link rel="stylesheet" type="text/css" href="brown.css">
- </head>
-
- <body>
-
- <div align="right">Getting Started with Javassist</div>
-
- <div align="left"><a href="tutorial2.html">Previous page</a></div>
-
- <p>
- <a href="#intro">5. Bytecode level API</a>
- <ul>
- <li><a href="#classfile">Obtaining a <code>ClassFile</code> object</a>
- <br><li><a href="#member">Adding and removing a member</a>
- <br><li><a href="#traverse">Traversing a method body</a>
- <br><li><a href="#bytecode">Producing a bytecode sequence</a>
-
- </ul>
-
-
- <p><br>
-
- <a name="intro">
- <h2>5. Bytecode level API</h2>
-
- <p>
- Javassist also provides lower-level API for directly editing
- a class file. To use this level of API, you need detailed
- knowledge of the Java bytecode and the class file format
- while this level of API allows you any kind of modification
- of class files.
-
- <a name="classfile">
- <h3>5.1 Obtaining a <code>ClassFile</code> object</h3>
-
- <p>A <code>javassist.bytecode.ClassFile</code> object represents
- a class file. To obtian this object, <code>getClassFile()</code>
- in <code>CtClass</code> should be called.
-
- <p>Otherwise, you can construct a
- <code>javassist.bytecode.ClassFile</code> directly from a class file.
- For example,
-
- <ul><pre>
- BufferedInputStream fin
- = new BufferedInputStream(new FileInputStream("Point.class"));
- ClassFile cf = new ClassFile(new DataInputStream(fin));
- </pre></ul>
-
- <p>
- This code snippet creats a <code>ClassFile</code> object from
- <code>Point.class</code>.
-
- <p>
- A <code>ClassFile</code> object can be written back to a
- class file. <code>write()</code> in <code>ClassFile</code>
- writes the contents of the class file to a given
- <code>DataOutputStream</code>.
-
- <p><br>
-
- <a name="member">
- <h3>5.2 Adding and removing a member</h3>
-
- <p>
- <code>ClassFile</code> provides <code>addField()</code> and
- <code>addMethod()</code> for adding a field or a method (note that
- a constructor is regarded as a method at the bytecode level).
- It also provides <code>addAttribute()</code> for adding an attribute
- to the class file.
-
- <p>
- Note that <code>FieldInfo</code>, <code>MethodInfo</code>, and
- <code>AttributeInfo</code> objects include a link to a
- <code>ConstPool</code> (constant pool table) object. The <code>ConstPool</code>
- object must be common to the <code>ClassFile</code> object and
- a <code>FieldInfo</code> (or <code>MethodInfo</code> etc.) object
- that is added to that <code>ClassFile</code> object.
- In other words, a <code>FieldInfo</code> (or <code>MethodInfo</code> etc.) object
- must not be shared among different <code>ClassFile</code> objects.
-
- <p>
- To remove a field or a method,
- you must first obtain a <code>java.util.List</code>
- object containing all the fields of the class. <code>getFields()</code>
- and <code>getMethods()</code> return the lists. A field or a method can
- be removed by calling <code>remove()</code> on the <code>List</code> object.
- An attribute can be removed in a similar way.
- Call <code>getAttributes()</code> in <code>FieldInfo</code> or
- <code>MethodInfo</code> to obtain the list of attributes,
- and remove one from the list.
-
-
- <p><br>
-
- <a name="traverse">
- <h3>5.3 Traversing a method body</h3>
-
- <p>
- To examine every bytecode instruction in a method body,
- <code>CodeIterator</code> is useful. To otbain this object,
- do as follows:
-
- <ul><pre>
- ClassFile cf = ... ;
- MethodInfo minfo = cf.getMethod("move"); // we assume move is not overloaded.
- CodeAttribute ca = minfo.getCodeAttribute();
- CodeIterator i = ca.iterator();
- </pre></ul>
-
- <p>
- A <code>CodeIterator</code> object allows you to visit every
- bytecode instruction one by one from the beginning to the end.
- The following methods are part of the methods declared in
- <code>CodeIterator</code>:
-
- <ul>
- <li><code>void begin()</code><br>
- Move to the first instruction.<br>
- <li><code>void move(int index)</code><br>
- Move to the instruction specified by the given index.<br>
- <li><code>hasNext()</code><br>
- Returns true if there is more instructions.<br>
- <li><code>next()</code><br>
- Returns the index of the next instruction.
- <em>Note that it does not return the opcode of the next
- instruction.</em><br>
- <li><code>int byteAt(int index)</code><br>
- Returns the unsigned 8bit value at the index.<br>
- <li><code>int u16bitAt(int index)</code><br>
- Returns the unsigned 16bit value at the index.<br>
- <li><code>int write(byte[] code, int index)</code><br>
- Writes a byte array at the index.<br>
- <li><code>void insert(int index, byte[] code)</code><br>
- Inserts a byte array at the index.
- Branch offsets etc. are automatically adjusted.<br>
- </ul>
-
- <p><br>
-
- <a name="bytecode">
- <h3>5.4 Producing a bytecode sequence</h3>
-
- <p>
- A <code>Bytecode</code> object represents a sequence of bytecode
- instructions. It is a growable array of bytecode.
- Here is a sample code snippet:
-
- <ul><pre>
- ConstPool cp = ...; // constant pool table
- Bytecode b = new Bytecode(cp, 1, 0);
- b.addIconst(3);
- b.addReturn(CtClass.intType);
- CodeAttribute ca = b.toCodeAttribute();
- </pre></ul>
-
- <p>
- This produces the code attribute representing the following sequence:
-
- <ul><pre>
- iconst_3
- ireturn
- </pre></ul>
-
- <p>
- You can also obtain a byte array containing this sequence by
- calling <code>get()</code> in <code>Bytecode</code>. The
- obtained array can be inserted in another code attribute.
-
- <p>
- While <code>Bytecode</code> provides a number of methods for adding a
- specific instruction to the sequence, it provides
- <code>addOpcode()</code> for adding an 8bit opcode and
- <code>addIndex()</code> for adding an index.
- The 8bit value of each opcode is defined in the <code>Opcode</code>
- interface.
-
- <p>
- <code>addOpcode()</code> and other methods for adding a specific
- instruction are automatically maintain the maximum stack depth
- unless the control flow does not include a branch.
- This value can be obtained by calling <code>getMaxStack()</code>
- on the <code>Bytecode</code> object.
- It is also reflected on the <code>CodeAttribute</code> object
- constructed from the <code>Bytecode</code> object.
- To recompute the maximum stack depth of a method body,
- call <code>computeMaxStack()</code> in <code>CodeAttribute</code>.
-
- <p><br>
-
- <a href="tutorial2.html">Previous page</a>
-
- <hr>
- Java(TM) is a trademark of Sun Microsystems, Inc.<br>
- Copyright (C) 2000-2004 by Shigeru Chiba, All rights reserved.
- </body>
- </html>
|