xref: /aosp_15_r20/external/javassist/tutorial/tutorial3.html (revision f1fbf3c2ab775ce834e0af96b7a85bdc7a0eac65)
1*f1fbf3c2SXin Li<html>
2*f1fbf3c2SXin Li<head>
3*f1fbf3c2SXin Li   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
4*f1fbf3c2SXin Li   <title>Javassist Tutorial</title>
5*f1fbf3c2SXin Li   <link rel="stylesheet" type="text/css" href="brown.css">
6*f1fbf3c2SXin Li</head>
7*f1fbf3c2SXin Li
8*f1fbf3c2SXin Li<body>
9*f1fbf3c2SXin Li
10*f1fbf3c2SXin Li<div align="right">Getting Started with Javassist</div>
11*f1fbf3c2SXin Li
12*f1fbf3c2SXin Li<div align="left"><a href="tutorial2.html">Previous page</a></div>
13*f1fbf3c2SXin Li
14*f1fbf3c2SXin Li<p>
15*f1fbf3c2SXin Li<a href="#intro">5. Bytecode level API</a>
16*f1fbf3c2SXin Li<ul>
17*f1fbf3c2SXin Li<li><a href="#classfile">Obtaining a <code>ClassFile</code> object</a>
18*f1fbf3c2SXin Li<br><li><a href="#member">Adding and removing a member</a>
19*f1fbf3c2SXin Li<br><li><a href="#traverse">Traversing a method body</a>
20*f1fbf3c2SXin Li<br><li><a href="#bytecode">Producing a bytecode sequence</a>
21*f1fbf3c2SXin Li<br><li><a href="#annotation">Annotations (Meta tags)</a>
22*f1fbf3c2SXin Li
23*f1fbf3c2SXin Li</ul>
24*f1fbf3c2SXin Li
25*f1fbf3c2SXin Li<p><a href="#generics">6. Generics</a>
26*f1fbf3c2SXin Li
27*f1fbf3c2SXin Li<p><a href="#varargs">7. Varargs</a>
28*f1fbf3c2SXin Li
29*f1fbf3c2SXin Li<p><a href="#j2me">8. J2ME</a>
30*f1fbf3c2SXin Li
31*f1fbf3c2SXin Li<p><a href="#boxing">9. Boxing/Unboxing
32*f1fbf3c2SXin Li
33*f1fbf3c2SXin Li<p><a href="#debug">10. Debug</a>
34*f1fbf3c2SXin Li
35*f1fbf3c2SXin Li<p><br>
36*f1fbf3c2SXin Li
37*f1fbf3c2SXin Li<a name="intro">
38*f1fbf3c2SXin Li<h2>5. Bytecode level API</h2>
39*f1fbf3c2SXin Li
40*f1fbf3c2SXin Li<p>
41*f1fbf3c2SXin LiJavassist also provides lower-level API for directly editing
42*f1fbf3c2SXin Lia class file.  To use this level of API, you need detailed
43*f1fbf3c2SXin Liknowledge of the Java bytecode and the class file format
44*f1fbf3c2SXin Liwhile this level of API allows you any kind of modification
45*f1fbf3c2SXin Liof class files.
46*f1fbf3c2SXin Li
47*f1fbf3c2SXin Li<p>
48*f1fbf3c2SXin LiIf you want to just produce a simple class file,
49*f1fbf3c2SXin Li<code>javassist.bytecode.ClassFileWriter</code> might provide
50*f1fbf3c2SXin Lithe best API for you.  It is much faster than
51*f1fbf3c2SXin Li<code>javassist.bytecode.ClassFile</code> although its API
52*f1fbf3c2SXin Liis minimum.
53*f1fbf3c2SXin Li
54*f1fbf3c2SXin Li<a name="classfile">
55*f1fbf3c2SXin Li<h3>5.1 Obtaining a <code>ClassFile</code> object</h3>
56*f1fbf3c2SXin Li
57*f1fbf3c2SXin Li<p>A <code>javassist.bytecode.ClassFile</code> object represents
58*f1fbf3c2SXin Lia class file.  To obtian this object, <code>getClassFile()</code>
59*f1fbf3c2SXin Liin <code>CtClass</code> should be called.
60*f1fbf3c2SXin Li
61*f1fbf3c2SXin Li<p>Otherwise, you can construct a
62*f1fbf3c2SXin Li<code>javassist.bytecode.ClassFile</code> directly from a class file.
63*f1fbf3c2SXin LiFor example,
64*f1fbf3c2SXin Li
65*f1fbf3c2SXin Li<ul><pre>
66*f1fbf3c2SXin LiBufferedInputStream fin
67*f1fbf3c2SXin Li    = new BufferedInputStream(new FileInputStream("Point.class"));
68*f1fbf3c2SXin LiClassFile cf = new ClassFile(new DataInputStream(fin));
69*f1fbf3c2SXin Li</pre></ul>
70*f1fbf3c2SXin Li
71*f1fbf3c2SXin Li<p>
72*f1fbf3c2SXin LiThis code snippet creats a <code>ClassFile</code> object from
73*f1fbf3c2SXin Li<code>Point.class</code>.
74*f1fbf3c2SXin Li
75*f1fbf3c2SXin Li<p>
76*f1fbf3c2SXin LiA <code>ClassFile</code> object can be written back to a
77*f1fbf3c2SXin Liclass file.  <code>write()</code> in <code>ClassFile</code>
78*f1fbf3c2SXin Liwrites the contents of the class file to a given
79*f1fbf3c2SXin Li<code>DataOutputStream</code>.
80*f1fbf3c2SXin Li
81*f1fbf3c2SXin Li<p>You can create a new class file from scratch.  For example,
82*f1fbf3c2SXin Li<blockquote><pre>
83*f1fbf3c2SXin LiClassFile cf = new ClassFile(false, "test.Foo", null);
84*f1fbf3c2SXin Licf.setInterfaces(new String[] { "java.lang.Cloneable" });
85*f1fbf3c2SXin Li
86*f1fbf3c2SXin LiFieldInfo f = new FieldInfo(cf.getConstPool(), "width", "I");
87*f1fbf3c2SXin Lif.setAccessFlags(AccessFlag.PUBLIC);
88*f1fbf3c2SXin Licf.addField(f);
89*f1fbf3c2SXin Li
90*f1fbf3c2SXin Licf.write(new DataOutputStream(new FileOutputStream("Foo.class")));
91*f1fbf3c2SXin Li</pre></blockquote>
92*f1fbf3c2SXin Li
93*f1fbf3c2SXin Li<p>this code generates a class file <code>Foo.class</code> that contains
94*f1fbf3c2SXin Lithe implementation of the following class:
95*f1fbf3c2SXin Li
96*f1fbf3c2SXin Li<blockquote><pre>
97*f1fbf3c2SXin Lipackage test;
98*f1fbf3c2SXin Liclass Foo implements Cloneable {
99*f1fbf3c2SXin Li    public int width;
100*f1fbf3c2SXin Li}
101*f1fbf3c2SXin Li</pre></blockquote>
102*f1fbf3c2SXin Li
103*f1fbf3c2SXin Li<p><br>
104*f1fbf3c2SXin Li
105*f1fbf3c2SXin Li<a name="member">
106*f1fbf3c2SXin Li<h3>5.2 Adding and removing a member</h3>
107*f1fbf3c2SXin Li
108*f1fbf3c2SXin Li<p>
109*f1fbf3c2SXin Li<code>ClassFile</code> provides <code>addField()</code> and
110*f1fbf3c2SXin Li<code>addMethod()</code> for adding a field or a method (note that
111*f1fbf3c2SXin Lia constructor is regarded as a method at the bytecode level).
112*f1fbf3c2SXin LiIt also provides <code>addAttribute()</code> for adding an attribute
113*f1fbf3c2SXin Lito the class file.
114*f1fbf3c2SXin Li
115*f1fbf3c2SXin Li<p>
116*f1fbf3c2SXin LiNote that <code>FieldInfo</code>, <code>MethodInfo</code>, and
117*f1fbf3c2SXin Li<code>AttributeInfo</code> objects include a link to a
118*f1fbf3c2SXin Li<code>ConstPool</code> (constant pool table) object.  The <code>ConstPool</code>
119*f1fbf3c2SXin Liobject must be common to the <code>ClassFile</code> object and
120*f1fbf3c2SXin Lia <code>FieldInfo</code> (or <code>MethodInfo</code> etc.) object
121*f1fbf3c2SXin Lithat is added to that <code>ClassFile</code> object.
122*f1fbf3c2SXin LiIn other words, a <code>FieldInfo</code> (or <code>MethodInfo</code> etc.) object
123*f1fbf3c2SXin Limust not be shared among different <code>ClassFile</code> objects.
124*f1fbf3c2SXin Li
125*f1fbf3c2SXin Li<p>
126*f1fbf3c2SXin LiTo remove a field or a method from a <code>ClassFile</code> object,
127*f1fbf3c2SXin Liyou must first obtain a <code>java.util.List</code>
128*f1fbf3c2SXin Liobject containing all the fields of the class.  <code>getFields()</code>
129*f1fbf3c2SXin Liand <code>getMethods()</code> return the lists.  A field or a method can
130*f1fbf3c2SXin Libe removed by calling <code>remove()</code> on the <code>List</code> object.
131*f1fbf3c2SXin LiAn attribute can be removed in a similar way.
132*f1fbf3c2SXin LiCall <code>getAttributes()</code> in <code>FieldInfo</code> or
133*f1fbf3c2SXin Li<code>MethodInfo</code> to obtain the list of attributes,
134*f1fbf3c2SXin Liand remove one from the list.
135*f1fbf3c2SXin Li
136*f1fbf3c2SXin Li
137*f1fbf3c2SXin Li<p><br>
138*f1fbf3c2SXin Li
139*f1fbf3c2SXin Li<a name="traverse">
140*f1fbf3c2SXin Li<h3>5.3 Traversing a method body</h3>
141*f1fbf3c2SXin Li
142*f1fbf3c2SXin Li<p>
143*f1fbf3c2SXin LiTo examine every bytecode instruction in a method body,
144*f1fbf3c2SXin Li<code>CodeIterator</code> is useful.  To otbain this object,
145*f1fbf3c2SXin Lido as follows:
146*f1fbf3c2SXin Li
147*f1fbf3c2SXin Li<ul><pre>
148*f1fbf3c2SXin LiClassFile cf = ... ;
149*f1fbf3c2SXin LiMethodInfo minfo = cf.getMethod("move");    // we assume move is not overloaded.
150*f1fbf3c2SXin LiCodeAttribute ca = minfo.getCodeAttribute();
151*f1fbf3c2SXin LiCodeIterator i = ca.iterator();
152*f1fbf3c2SXin Li</pre></ul>
153*f1fbf3c2SXin Li
154*f1fbf3c2SXin Li<p>
155*f1fbf3c2SXin LiA <code>CodeIterator</code> object allows you to visit every
156*f1fbf3c2SXin Libytecode instruction one by one from the beginning to the end.
157*f1fbf3c2SXin LiThe following methods are part of the methods declared in
158*f1fbf3c2SXin Li<code>CodeIterator</code>:
159*f1fbf3c2SXin Li
160*f1fbf3c2SXin Li<ul>
161*f1fbf3c2SXin Li<li><code>void begin()</code><br>
162*f1fbf3c2SXin LiMove to the first instruction.<br>
163*f1fbf3c2SXin Li<li><code>void move(int index)</code><br>
164*f1fbf3c2SXin LiMove to the instruction specified by the given index.<br>
165*f1fbf3c2SXin Li<li><code>boolean hasNext()</code><br>
166*f1fbf3c2SXin LiReturns true if there is more instructions.<br>
167*f1fbf3c2SXin Li<li><code>int next()</code><br>
168*f1fbf3c2SXin LiReturns the index of the next instruction.<br>
169*f1fbf3c2SXin Li<em>Note that it does not return the opcode of the next
170*f1fbf3c2SXin Liinstruction.</em><br>
171*f1fbf3c2SXin Li<li><code>int byteAt(int index)</code><br>
172*f1fbf3c2SXin LiReturns the unsigned 8bit value at the index.<br>
173*f1fbf3c2SXin Li<li><code>int u16bitAt(int index)</code><br>
174*f1fbf3c2SXin LiReturns the unsigned 16bit value at the index.<br>
175*f1fbf3c2SXin Li<li><code>int write(byte[] code, int index)</code><br>
176*f1fbf3c2SXin LiWrites a byte array at the index.<br>
177*f1fbf3c2SXin Li<li><code>void insert(int index, byte[] code)</code><br>
178*f1fbf3c2SXin LiInserts a byte array at the index.
179*f1fbf3c2SXin LiBranch offsets etc. are automatically adjusted.<br>
180*f1fbf3c2SXin Li</ul>
181*f1fbf3c2SXin Li
182*f1fbf3c2SXin Li<p>The following code snippet displays all the instructions included
183*f1fbf3c2SXin Liin a method body:
184*f1fbf3c2SXin Li
185*f1fbf3c2SXin Li<ul><pre>
186*f1fbf3c2SXin LiCodeIterator ci = ... ;
187*f1fbf3c2SXin Liwhile (ci.hasNext()) {
188*f1fbf3c2SXin Li    int index = ci.next();
189*f1fbf3c2SXin Li    int op = ci.byteAt(index);
190*f1fbf3c2SXin Li    System.out.println(Mnemonic.OPCODE[op]);
191*f1fbf3c2SXin Li}
192*f1fbf3c2SXin Li</pre></ul>
193*f1fbf3c2SXin Li
194*f1fbf3c2SXin Li<p><br>
195*f1fbf3c2SXin Li
196*f1fbf3c2SXin Li<a name="bytecode">
197*f1fbf3c2SXin Li<h3>5.4 Producing a bytecode sequence</h3>
198*f1fbf3c2SXin Li
199*f1fbf3c2SXin Li<p>
200*f1fbf3c2SXin LiA <code>Bytecode</code> object represents a sequence of bytecode
201*f1fbf3c2SXin Liinstructions.  It is a growable array of bytecode.
202*f1fbf3c2SXin LiHere is a sample code snippet:
203*f1fbf3c2SXin Li
204*f1fbf3c2SXin Li<ul><pre>
205*f1fbf3c2SXin LiConstPool cp = ...;    // constant pool table
206*f1fbf3c2SXin LiBytecode b = new Bytecode(cp, 1, 0);
207*f1fbf3c2SXin Lib.addIconst(3);
208*f1fbf3c2SXin Lib.addReturn(CtClass.intType);
209*f1fbf3c2SXin LiCodeAttribute ca = b.toCodeAttribute();
210*f1fbf3c2SXin Li</pre></ul>
211*f1fbf3c2SXin Li
212*f1fbf3c2SXin Li<p>
213*f1fbf3c2SXin LiThis produces the code attribute representing the following sequence:
214*f1fbf3c2SXin Li
215*f1fbf3c2SXin Li<ul><pre>
216*f1fbf3c2SXin Liiconst_3
217*f1fbf3c2SXin Liireturn
218*f1fbf3c2SXin Li</pre></ul>
219*f1fbf3c2SXin Li
220*f1fbf3c2SXin Li<p>
221*f1fbf3c2SXin LiYou can also obtain a byte array containing this sequence by
222*f1fbf3c2SXin Licalling <code>get()</code> in <code>Bytecode</code>.  The
223*f1fbf3c2SXin Liobtained array can be inserted in another code attribute.
224*f1fbf3c2SXin Li
225*f1fbf3c2SXin Li<p>
226*f1fbf3c2SXin LiWhile <code>Bytecode</code> provides a number of methods for adding a
227*f1fbf3c2SXin Lispecific instruction to the sequence, it provides
228*f1fbf3c2SXin Li<code>addOpcode()</code> for adding an 8bit opcode and
229*f1fbf3c2SXin Li<code>addIndex()</code> for adding an index.
230*f1fbf3c2SXin LiThe 8bit value of each opcode is defined in the <code>Opcode</code>
231*f1fbf3c2SXin Liinterface.
232*f1fbf3c2SXin Li
233*f1fbf3c2SXin Li<p>
234*f1fbf3c2SXin Li<code>addOpcode()</code> and other methods for adding a specific
235*f1fbf3c2SXin Liinstruction are automatically maintain the maximum stack depth
236*f1fbf3c2SXin Liunless the control flow does not include a branch.
237*f1fbf3c2SXin LiThis value can be obtained by calling <code>getMaxStack()</code>
238*f1fbf3c2SXin Lion the <code>Bytecode</code> object.
239*f1fbf3c2SXin LiIt is also reflected on the <code>CodeAttribute</code> object
240*f1fbf3c2SXin Liconstructed from the <code>Bytecode</code> object.
241*f1fbf3c2SXin LiTo recompute the maximum stack depth of a method body,
242*f1fbf3c2SXin Licall <code>computeMaxStack()</code> in <code>CodeAttribute</code>.
243*f1fbf3c2SXin Li
244*f1fbf3c2SXin Li<p><code>Bytecode</code> can be used to construct a method.
245*f1fbf3c2SXin LiFor example,
246*f1fbf3c2SXin Li
247*f1fbf3c2SXin Li<blockquote><pre>
248*f1fbf3c2SXin LiClassFile cf = ...
249*f1fbf3c2SXin LiBytecode code = new Bytecode(cf.getConstPool());
250*f1fbf3c2SXin Licode.addAload(0);
251*f1fbf3c2SXin Licode.addInvokespecial("java/lang/Object", MethodInfo.nameInit, "()V");
252*f1fbf3c2SXin Licode.addReturn(null);
253*f1fbf3c2SXin Licode.setMaxLocals(1);
254*f1fbf3c2SXin Li
255*f1fbf3c2SXin LiMethodInfo minfo = new MethodInfo(cf.getConstPool(), MethodInfo.nameInit, "()V");
256*f1fbf3c2SXin Liminfo.setCodeAttribute(code.toCodeAttribute());
257*f1fbf3c2SXin Licf.addMethod(minfo);
258*f1fbf3c2SXin Li</pre></blockquote>
259*f1fbf3c2SXin Li
260*f1fbf3c2SXin Li<p>this code makes the default constructor and adds it to the class specified
261*f1fbf3c2SXin Liby <code>cf</code>.  The <code>Bytecode</code> object is first converted into
262*f1fbf3c2SXin Lia <code>CodeAttribute</code> object and then added to the method specified
263*f1fbf3c2SXin Liby <code>minfo</code>.  The method is finally added to a class file <code>cf</code>.
264*f1fbf3c2SXin Li
265*f1fbf3c2SXin Li<p><br>
266*f1fbf3c2SXin Li
267*f1fbf3c2SXin Li<a name="annotation">
268*f1fbf3c2SXin Li<h3>5.5 Annotations (Meta tags)</h3>
269*f1fbf3c2SXin Li
270*f1fbf3c2SXin Li<p>Annotations are stored in a class file
271*f1fbf3c2SXin Lias runtime invisible (or visible) annotations attribute.
272*f1fbf3c2SXin LiThese attributes can be obtained from <code>ClassFile</code>,
273*f1fbf3c2SXin Li<code>MethodInfo</code>, or <code>FieldInfo</code> objects.
274*f1fbf3c2SXin LiCall <code>getAttribute(AnnotationsAttribute.invisibleTag)</code>
275*f1fbf3c2SXin Lion those objects.  For more details, see the javadoc manual
276*f1fbf3c2SXin Liof <code>javassist.bytecode.AnnotationsAttribute</code> class
277*f1fbf3c2SXin Liand the <code>javassist.bytecode.annotation</code> package.
278*f1fbf3c2SXin Li
279*f1fbf3c2SXin Li<p>Javassist also let you access annotations by the higher-level
280*f1fbf3c2SXin LiAPI.
281*f1fbf3c2SXin LiIf you want to access annotations through <code>CtClass</code>,
282*f1fbf3c2SXin Licall <code>getAnnotations()</code> in <code>CtClass</code> or
283*f1fbf3c2SXin Li<code>CtBehavior</code>.
284*f1fbf3c2SXin Li
285*f1fbf3c2SXin Li<p><br>
286*f1fbf3c2SXin Li
287*f1fbf3c2SXin Li<h2><a name="generics">6. Generics</a></h2>
288*f1fbf3c2SXin Li
289*f1fbf3c2SXin Li<p>The lower-level API of Javassist fully supports generics
290*f1fbf3c2SXin Liintroduced by Java 5.  On the other hand, the higher-level
291*f1fbf3c2SXin LiAPI such as <code>CtClass</code> does not directly support
292*f1fbf3c2SXin Ligenerics.  However, this is not a serious problem for bytecode
293*f1fbf3c2SXin Litransformation.
294*f1fbf3c2SXin Li
295*f1fbf3c2SXin Li<p>The generics of Java is implemented by the erasure technique.
296*f1fbf3c2SXin LiAfter compilation, all type parameters are dropped off.  For
297*f1fbf3c2SXin Liexample, suppose that your source code declares a parameterized
298*f1fbf3c2SXin Litype <code>Vector&lt;String&gt;</code>:
299*f1fbf3c2SXin Li
300*f1fbf3c2SXin Li<ul><pre>
301*f1fbf3c2SXin LiVector&lt;String&gt; v = new Vector&lt;String&gt();
302*f1fbf3c2SXin Li  :
303*f1fbf3c2SXin LiString s = v.get(0);
304*f1fbf3c2SXin Li</pre></ul>
305*f1fbf3c2SXin Li
306*f1fbf3c2SXin Li<p>The compiled bytecode is equivalent to the following code:
307*f1fbf3c2SXin Li
308*f1fbf3c2SXin Li<ul><pre>
309*f1fbf3c2SXin LiVector v = new Vector();
310*f1fbf3c2SXin Li  :
311*f1fbf3c2SXin LiString s = (String)v.get(0);
312*f1fbf3c2SXin Li</pre></ul>
313*f1fbf3c2SXin Li
314*f1fbf3c2SXin Li<p>So when you write a bytecode transformer, you can just drop
315*f1fbf3c2SXin Lioff all type parameters.  Because the compiler embedded in Javassist
316*f1fbf3c2SXin Lidoes not support generics,
317*f1fbf3c2SXin Liyou must insert an explicit type cast at the
318*f1fbf3c2SXin Licaller site if the source code is compiled by Javassist, for example,
319*f1fbf3c2SXin Lithrough <code>CtMethod.make()</code>.  No type cast
320*f1fbf3c2SXin Liis necessary if the source code is compiled by a normal Java compiler
321*f1fbf3c2SXin Lisuch as <code>javac</code>.
322*f1fbf3c2SXin Li
323*f1fbf3c2SXin Li<p>For example, if you have a class:
324*f1fbf3c2SXin Li
325*f1fbf3c2SXin Li<ul><pre>
326*f1fbf3c2SXin Lipublic class Wrapper&lt;T&gt; {
327*f1fbf3c2SXin Li  T value;
328*f1fbf3c2SXin Li  public Wrapper(T t) { value = t; }
329*f1fbf3c2SXin Li}
330*f1fbf3c2SXin Li</pre></ul>
331*f1fbf3c2SXin Li
332*f1fbf3c2SXin Li<p>and want to add an interface <code>Getter&lt;T&gt;</code> to the
333*f1fbf3c2SXin Liclass <code>Wrapper&lt;T&gt;</code>:
334*f1fbf3c2SXin Li
335*f1fbf3c2SXin Li<ul><pre>
336*f1fbf3c2SXin Lipublic interface Getter&lt;T&gt; {
337*f1fbf3c2SXin Li  T get();
338*f1fbf3c2SXin Li}
339*f1fbf3c2SXin Li</pre></ul>
340*f1fbf3c2SXin Li
341*f1fbf3c2SXin Li<p>then the interface you really have to add is <code>Getter</code>
342*f1fbf3c2SXin Li(the type parameters <code>&lt;T&gt;</code> drops off)
343*f1fbf3c2SXin Liand the method you also have to add to the <code>Wrapper</code>
344*f1fbf3c2SXin Liclass is this simple one:
345*f1fbf3c2SXin Li
346*f1fbf3c2SXin Li<ul><pre>
347*f1fbf3c2SXin Lipublic Object get() { return value; }
348*f1fbf3c2SXin Li</pre></ul>
349*f1fbf3c2SXin Li
350*f1fbf3c2SXin Li<p>Note that no type parameters are necessary.
351*f1fbf3c2SXin LiSince <code>get</code> returns an <code>Object</code>, an explicit type cast
352*f1fbf3c2SXin Liis needed at the caller site if the source code is compiled by Javassist.
353*f1fbf3c2SXin LiFor example, if the type parameter <code>T</code>
354*f1fbf3c2SXin Liis <code>String</code>, then <code>(String)</code> must be inserted as follows:
355*f1fbf3c2SXin Li
356*f1fbf3c2SXin Li<ul><pre>
357*f1fbf3c2SXin LiWrapper w = ...
358*f1fbf3c2SXin LiString s = (String)w.get();
359*f1fbf3c2SXin Li</pre></ul>
360*f1fbf3c2SXin Li
361*f1fbf3c2SXin Li<p>The type cast is not needed if the source code is compiled by a normal Java
362*f1fbf3c2SXin Licompiler because it will automatically insert a type cast.
363*f1fbf3c2SXin Li
364*f1fbf3c2SXin Li<p>If you need to make type parameters accessible through reflection
365*f1fbf3c2SXin Liduring runtime, you have to add generic signatures to the class file.
366*f1fbf3c2SXin LiFor more details, see the API documentation (javadoc) of the
367*f1fbf3c2SXin Li<code>setGenericSignature</code> method in the <code>CtClass</code>.
368*f1fbf3c2SXin Li
369*f1fbf3c2SXin Li<p><br>
370*f1fbf3c2SXin Li
371*f1fbf3c2SXin Li<h2><a name="varargs">7. Varargs</a></h2>
372*f1fbf3c2SXin Li
373*f1fbf3c2SXin Li<p>Currently, Javassist does not directly support varargs.  So to make a method with varargs,
374*f1fbf3c2SXin Liyou must explicitly set a method modifier.  But this is easy.
375*f1fbf3c2SXin LiSuppose that now you want to make the following method:
376*f1fbf3c2SXin Li
377*f1fbf3c2SXin Li<ul><pre>
378*f1fbf3c2SXin Lipublic int length(int... args) { return args.length; }
379*f1fbf3c2SXin Li</pre></ul>
380*f1fbf3c2SXin Li
381*f1fbf3c2SXin Li<p>The following code using Javassist will make the method shown above:
382*f1fbf3c2SXin Li
383*f1fbf3c2SXin Li<ul><pre>
384*f1fbf3c2SXin LiCtClass cc = /* target class */;
385*f1fbf3c2SXin LiCtMethod m = CtMethod.make("public int length(int[] args) { return args.length; }", cc);
386*f1fbf3c2SXin Lim.setModifiers(m.getModifiers() | Modifier.VARARGS);
387*f1fbf3c2SXin Licc.addMethod(m);
388*f1fbf3c2SXin Li<pre></ul>
389*f1fbf3c2SXin Li
390*f1fbf3c2SXin Li<p>The parameter type <code>int...</code> is changed into <code>int[]</code>
391*f1fbf3c2SXin Liand <code>Modifier.VARARGS</code> is added to the method modifiers.
392*f1fbf3c2SXin Li
393*f1fbf3c2SXin Li<p>To call this method in the source code compiled by the compiler embedded in Javassist,
394*f1fbf3c2SXin Liyou must write:
395*f1fbf3c2SXin Li
396*f1fbf3c2SXin Li<ul><pre>
397*f1fbf3c2SXin Lilength(new int[] { 1, 2, 3 });
398*f1fbf3c2SXin Li</pre></ul>
399*f1fbf3c2SXin Li
400*f1fbf3c2SXin Li<p>instead of this method call using the varargs mechanism:
401*f1fbf3c2SXin Li
402*f1fbf3c2SXin Li<ul><pre>
403*f1fbf3c2SXin Lilength(1, 2, 3);
404*f1fbf3c2SXin Li</pre></ul>
405*f1fbf3c2SXin Li
406*f1fbf3c2SXin Li<p><br>
407*f1fbf3c2SXin Li
408*f1fbf3c2SXin Li<h2><a name="j2me">8. J2ME</a></h2>
409*f1fbf3c2SXin Li
410*f1fbf3c2SXin Li<p>If you modify a class file for the J2ME execution environment,
411*f1fbf3c2SXin Liyou must perform <it>preverification</it>.  Preverifying is basically
412*f1fbf3c2SXin Liproducing stack maps, which is similar to stack map tables introduced
413*f1fbf3c2SXin Liinto J2SE at JDK 1.6.  Javassist maintains the stack maps for J2ME only if
414*f1fbf3c2SXin Li<code>javassist.bytecode.MethodInfo.doPreverify</code> is true.
415*f1fbf3c2SXin Li
416*f1fbf3c2SXin Li<p>You can also manually
417*f1fbf3c2SXin Liproduce a stack map for a modified method.
418*f1fbf3c2SXin LiFor a given method represented by a <code>CtMethod</code> object <code>m</code>,
419*f1fbf3c2SXin Liyou can produce a stack map by calling the following methods:
420*f1fbf3c2SXin Li
421*f1fbf3c2SXin Li<ul><pre>
422*f1fbf3c2SXin Lim.getMethodInfo().rebuildStackMapForME(cpool);
423*f1fbf3c2SXin Li</pre></ul>
424*f1fbf3c2SXin Li
425*f1fbf3c2SXin Li<p>Here, <code>cpool</code> is a <code>ClassPool</code> object, which is
426*f1fbf3c2SXin Liavailable by calling <code>getClassPool()</code> on a <code>CtClass</code>
427*f1fbf3c2SXin Liobject.  A <code>ClassPool</code> object is responsible for finding
428*f1fbf3c2SXin Liclass files from given class pathes.  To obtain all the <code>CtMethod</code>
429*f1fbf3c2SXin Liobjects, call the <code>getDeclaredMethods</code> method on a <code>CtClass</code> object.
430*f1fbf3c2SXin Li
431*f1fbf3c2SXin Li<p><br>
432*f1fbf3c2SXin Li
433*f1fbf3c2SXin Li<h2><a name="boxing">9. Boxing/Unboxing</h2>
434*f1fbf3c2SXin Li
435*f1fbf3c2SXin Li<p>Boxing and unboxing in Java are syntactic sugar.  There is no bytecode for
436*f1fbf3c2SXin Liboxing or unboxing.  So the compiler of Javassist does not support them.
437*f1fbf3c2SXin LiFor example, the following statement is valid in Java:
438*f1fbf3c2SXin Li
439*f1fbf3c2SXin Li<ul><pre>
440*f1fbf3c2SXin LiInteger i = 3;
441*f1fbf3c2SXin Li</pre></ul>
442*f1fbf3c2SXin Li
443*f1fbf3c2SXin Li<p>since boxing is implicitly performed.  For Javassist, however, you must explicitly
444*f1fbf3c2SXin Liconvert a value type from <code>int</code> to <code>Integer</code>:
445*f1fbf3c2SXin Li
446*f1fbf3c2SXin Li<ul><pre>
447*f1fbf3c2SXin LiInteger i = new Integer(3);
448*f1fbf3c2SXin Li</pre></ul>
449*f1fbf3c2SXin Li
450*f1fbf3c2SXin Li<p><br>
451*f1fbf3c2SXin Li
452*f1fbf3c2SXin Li<h2><a name="debug">10. Debug</h2>
453*f1fbf3c2SXin Li
454*f1fbf3c2SXin Li<p>Set <code>CtClass.debugDump</code> to a directory name.
455*f1fbf3c2SXin LiThen all class files modified and generated by Javassist are saved in that
456*f1fbf3c2SXin Lidirectory.  To stop this, set <code>CtClass.debugDump</code> to null.
457*f1fbf3c2SXin LiThe default value is null.
458*f1fbf3c2SXin Li
459*f1fbf3c2SXin Li<p>For example,
460*f1fbf3c2SXin Li
461*f1fbf3c2SXin Li<ul><pre>
462*f1fbf3c2SXin LiCtClass.debugDump = "./dump";
463*f1fbf3c2SXin Li</pre></ul>
464*f1fbf3c2SXin Li
465*f1fbf3c2SXin Li<p>All modified class files are saved in <code>./dump</code>.
466*f1fbf3c2SXin Li
467*f1fbf3c2SXin Li<p><br>
468*f1fbf3c2SXin Li
469*f1fbf3c2SXin Li<a href="tutorial2.html">Previous page</a>
470*f1fbf3c2SXin Li
471*f1fbf3c2SXin Li<hr>
472*f1fbf3c2SXin LiJava(TM) is a trademark of Sun Microsystems, Inc.<br>
473*f1fbf3c2SXin LiCopyright (C) 2000-2015 by Shigeru Chiba, All rights reserved.
474*f1fbf3c2SXin Li</body>
475*f1fbf3c2SXin Li</html>
476