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<String></code>: 299*f1fbf3c2SXin Li 300*f1fbf3c2SXin Li<ul><pre> 301*f1fbf3c2SXin LiVector<String> v = new Vector<String>(); 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<T> { 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<T></code> to the 333*f1fbf3c2SXin Liclass <code>Wrapper<T></code>: 334*f1fbf3c2SXin Li 335*f1fbf3c2SXin Li<ul><pre> 336*f1fbf3c2SXin Lipublic interface Getter<T> { 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><T></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