diff options
author | Shigeru Chiba <chiba@javassist.org> | 2015-05-23 02:41:30 +0900 |
---|---|---|
committer | Shigeru Chiba <chiba@javassist.org> | 2015-05-23 02:41:30 +0900 |
commit | 2c35b1080745871c3200753e905f25b748bc0053 (patch) | |
tree | 2de786b9e848f351b3feea060bceb12cb4c6a6bc /tutorial | |
parent | 29040740206ef778b2029e38656570f302dcff3a (diff) | |
download | javassist-2c35b1080745871c3200753e905f25b748bc0053.tar.gz javassist-2c35b1080745871c3200753e905f25b748bc0053.zip |
Initial commit
Diffstat (limited to 'tutorial')
-rw-r--r-- | tutorial/brown.css | 19 | ||||
-rw-r--r-- | tutorial/tutorial.html | 1105 | ||||
-rw-r--r-- | tutorial/tutorial2.html | 1633 | ||||
-rw-r--r-- | tutorial/tutorial3.html | 475 |
4 files changed, 0 insertions, 3232 deletions
diff --git a/tutorial/brown.css b/tutorial/brown.css deleted file mode 100644 index 7570549f..00000000 --- a/tutorial/brown.css +++ /dev/null @@ -1,19 +0,0 @@ -h1,h2,h3 { - color:#663300; - padding:4px 6px 6px 10px; - border-width:1px 0px 1px 0px; - border-color:#F5DEB3; - border-style:solid; -} - -h3 { - padding-left: 30px; -} - -h4 { - color:#663300; -} - -em { - color:#cc0000; -} diff --git a/tutorial/tutorial.html b/tutorial/tutorial.html deleted file mode 100644 index b8110390..00000000 --- a/tutorial/tutorial.html +++ /dev/null @@ -1,1105 +0,0 @@ -<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> - -<b> -<font size="+3"> -Getting Started with Javassist -</font> - -<p><font size="+2"> -Shigeru Chiba -</font> -</b> - -<p><div align="right"><a href="tutorial2.html">Next page</a></div> - -<ul>1. <a href="#read">Reading and writing bytecode</a> -<br>2. <a href="#pool">ClassPool</a> -<br>3. <a href="#load">Class loader</a> -<br>4. <a href="tutorial2.html#intro">Introspection and customization</a> -<br>5. <a href="tutorial3.html#intro">Bytecode level API</a> -<br>6. <a href="tutorial3.html#generics">Generics</a> -<br>7. <a href="tutorial3.html#varargs">Varargs</a> -<br>8. <a href="tutorial3.html#j2me">J2ME</a> -<br>9. <a href="tutorial3.html#boxing">Boxing/Unboxing</a> -<br>10. <a href="tutorial3.html#debug">Debug</a> -</ul> - -<p><br> - -<a name="read"> -<h2>1. Reading and writing bytecode</h2> - -<p>Javassist is a class library for dealing with Java bytecode. -Java bytecode is stored in a binary file called a class file. -Each class file contains one Java class or interface. - -<p>The class <code>Javassist.CtClass</code> is an abstract -representation of a class file. A <code>CtClass</code> (compile-time -class) object is a handle for dealing with a class file. The -following program is a very simple example: - -<ul><pre> -ClassPool pool = ClassPool.getDefault(); -CtClass cc = pool.get("test.Rectangle"); -cc.setSuperclass(pool.get("test.Point")); -cc.writeFile(); -</pre></ul> - -<p>This program first obtains a <code>ClassPool</code> object, which -controls bytecode modification with Javassist. The -<code>ClassPool</code> object is a container of <code>CtClass</code> -object representing a class file. It reads a class file on demand for -constructing a <code>CtClass</code> object and records the -constructed object for responding later accesses. - -To modify the definition of a class, the users must first obtain -from a <code>ClassPool</code> object -a reference to a <code>CtClass</code> object representing that class. -<code>get()</code> in <code>ClassPool</code> is used for this purpose. -In the case of the program shown above, the -<code>CtClass</code> object representing a class -<code>test.Rectangle</code> is obtained from the -<code>ClassPool</code> object and it is assigned to a variable -<code>cc</code>. -The <code>ClassPool</code> object returned by <code>getDefault()</code> -searches the default system search path. - -<p>From the implementation viewpoint, <code>ClassPool</code> is a hash -table of <code>CtClass</code> objects, which uses the class names as -keys. <code>get()</code> in <code>ClassPool</code> searches this hash -table to find a <code>CtClass</code> object associated with the -specified key. If such a <code>CtClass</code> object is not found, -<code>get()</code> reads a class file to construct a new -<code>CtClass</code> object, which is recorded in the hash table and -then returned as the resulting value of <code>get()</code>. - -<p>The <code>CtClass</code> object obtained from a <code>ClassPool</code> -object can be modified -(<a href="tutorial2.html#intro">details of how to modify -a <code>CtClass</code></a> will be presented later). -In the example above, it is modified so that the superclass of -<code>test.Rectangle</code> is changed into a class -<code>test.Point</code>. This change is reflected on the original -class file when <code>writeFile()</code> in <code>CtClass()</code> is -finally called. - -<p><code>writeFile()</code> translates the <code>CtClass</code> object -into a class file and writes it on a local disk. -Javassist also provides a method for directly obtaining the -modified bytecode. To obtain the bytecode, call <code>toBytecode()</code>: - -<ul><pre> -byte[] b = cc.toBytecode(); -</pre></ul> - -<p>You can directly load the <code>CtClass</code> as well: - -<ul><pre> -Class clazz = cc.toClass(); -</pre></ul> - -<p><code>toClass()</code> requests the context class loader for the current -thread to load the class file represented by the <code>CtClass</code>. It -returns a <code>java.lang.Class</code> object representing the loaded class. -For more details, please see <a href="#toclass">this section below</a>. - -<a name="def"> -<h4>Defining a new class</h4> - -<p>To define a new class from scratch, <code>makeClass()</code> -must be called on a <code>ClassPool</code>. - -<ul><pre> -ClassPool pool = ClassPool.getDefault(); -CtClass cc = pool.makeClass("Point"); -</pre></ul> - -<p>This program defines a class <code>Point</code> -including no members. -Member methods of <code>Point</code> can be created with -factory methods declared in <code>CtNewMethod</code> and -appended to <code>Point</code> with <code>addMethod()</code> -in <code>CtClass</code>. - -<p><code>makeClass()</code> cannot create a new interface; -<code>makeInterface()</code> in <code>ClassPool</code> can do. -Member methods in an interface can be created with -<code>abstractMethod()</code> in <code>CtNewMethod</code>. -Note that an interface method is an abstract method. - -<a name="frozenclasses"> -<h4>Frozen classes</h4></a> - -<p>If a <code>CtClass</code> object is converted into a class file by -<code>writeFile()</code>, <code>toClass()</code>, or -<code>toBytecode()</code>, Javassist freezes that <code>CtClass</code> -object. Further modifications of that <code>CtClass</code> object are -not permitted. This is for warning the developers when they attempt -to modify a class file that has been already loaded since the JVM does -not allow reloading a class. - -<p>A frozen <code>CtClass</code> can be defrost so that -modifications of the class definition will be permitted. For example, - -<ul><pre> -CtClasss cc = ...; - : -cc.writeFile(); -cc.defrost(); -cc.setSuperclass(...); // OK since the class is not frozen. -</pre></ul> - -<p>After <code>defrost()</code> is called, the <code>CtClass</code> -object can be modified again. - -<p>If <code>ClassPool.doPruning</code> is set to <code>true</code>, -then Javassist prunes the data structure contained -in a <code>CtClass</code> object -when Javassist freezes that object. -To reduce memory -consumption, pruning discards unnecessary attributes -(<code>attribute_info</code> structures) in that object. -For example, <code>Code_attribute</code> structures (method bodies) -are discarded. -Thus, after a -<code>CtClass</code> object is pruned, the bytecode of a method is not -accessible except method names, signatures, and annotations. -The pruned <code>CtClass</code> object cannot be defrost again. -The default value of <code>ClassPool.doPruning</code> is <code>false</code>. - -<p>To disallow pruning a particular <code>CtClass</code>, -<code>stopPruning()</code> must be called on that object in advance: - -<ul><pre> -CtClasss cc = ...; -cc.stopPruning(true); - : -cc.writeFile(); // convert to a class file. -// cc is not pruned. -</pre></ul> - -<p>The <code>CtClass</code> object <code>cc</code> is not pruned. -Thus it can be defrost after <code>writeFile()</code> is called. - -<ul><b>Note:</b> -While debugging, you might want to temporarily stop pruning and freezing -and write a modified class file to a disk drive. -<code>debugWriteFile()</code> is a convenient method -for that purpose. It stops pruning, writes a class file, defrosts it, -and turns pruning on again (if it was initially on). -</ul> - - - -<h4>Class search path</h4> - -<p>The default <code>ClassPool</code> returned -by a static method <code>ClassPool.getDefault()</code> -searches the same path that the underlying JVM (Java virtual machine) has. -<em>If a program is running on a web application server such as JBoss and Tomcat, -the <code>ClassPool</code> object may not be able to find user classes</em> -since such a web application server uses multiple class loaders as well as -the system class loader. In that case, an additional class path must be -registered to the <code>ClassPool</code>. Suppose that <code>pool</code> -refers to a <code>ClassPool</code> object: - -<ul><pre> -pool.insertClassPath(new ClassClassPath(this.getClass())); -</pre></ul> - -<p> -This statement registers the class path that was used for loading -the class of the object that <code>this</code> refers to. -You can use any <code>Class</code> object as an argument instead of -<code>this.getClass()</code>. The class path used for loading the -class represented by that <code>Class</code> object is registered. - -<p> -You can register a directory name as the class search path. -For example, the following code adds a directory -<code>/usr/local/javalib</code> -to the search path: - -<ul><pre> -ClassPool pool = ClassPool.getDefault(); -pool.insertClassPath("/usr/local/javalib"); -</pre></ul> - -<p>The search path that the users can add is not only a directory but also -a URL: - -<ul><pre> -ClassPool pool = ClassPool.getDefault(); -ClassPath cp = new URLClassPath("www.javassist.org", 80, "/java/", "org.javassist."); -pool.insertClassPath(cp); -</pre></ul> - -<p>This program adds "http://www.javassist.org:80/java/" to the class search -path. This URL is used only for searching classes belonging to a -package <code>org.javassist</code>. For example, to load a class -<code>org.javassist.test.Main</code>, its class file will be obtained from: - -<ul><pre>http://www.javassist.org:80/java/org/javassist/test/Main.class -</pre></ul> - -<p>Furthermore, you can directly give a byte array -to a <code>ClassPool</code> object -and construct a <code>CtClass</code> object from that array. To do this, -use <code>ByteArrayClassPath</code>. For example, - -<ul><pre> -ClassPool cp = ClassPool.getDefault(); -byte[] b = <em>a byte array</em>; -String name = <em>class name</em>; -cp.insertClassPath(new ByteArrayClassPath(name, b)); -CtClass cc = cp.get(name); -</pre></ul> - -<p>The obtained <code>CtClass</code> object represents -a class defined by the class file specified by <code>b</code>. -The <code>ClassPool</code> reads a class file from the given -<code>ByteArrayClassPath</code> if <code>get()</code> is called -and the class name given to <code>get()</code> is equal to -one specified by <code>name</code>. - -<p>If you do not know the fully-qualified name of the class, then you -can use <code>makeClass()</code> in <code>ClassPool</code>: - -<ul><pre> -ClassPool cp = ClassPool.getDefault(); -InputStream ins = <em>an input stream for reading a class file</em>; -CtClass cc = cp.makeClass(ins); -</pre></ul> - -<p><code>makeClass()</code> returns the <code>CtClass</code> object -constructed from the given input stream. You can use -<code>makeClass()</code> for eagerly feeding class files to -the <code>ClassPool</code> object. This might improve performance -if the search path includes a large jar file. Since -a <code>ClassPool</code> object reads a class file on demand, -it might repeatedly search the whole jar file for every class file. -<code>makeClass()</code> can be used for optimizing this search. -The <code>CtClass</code> constructed by <code>makeClass()</code> -is kept in the <code>ClassPool</code> object and the class file is never -read again. - -<p>The users can extend the class search path. They can define a new -class implementing <code>ClassPath</code> interface and give an -instance of that class to <code>insertClassPath()</code> in -<code>ClassPool</code>. This allows a non-standard resource to be -included in the search path. - -<p><br> - -<a name="pool"> -<h2>2. ClassPool</h2> - -<p> -A <code>ClassPool</code> object is a container of <code>CtClass</code> -objects. Once a <code>CtClass</code> object is created, it is -recorded in a <code>ClassPool</code> for ever. This is because a -compiler may need to access the <code>CtClass</code> object later when -it compiles source code that refers to the class represented by that -<code>CtClass</code>. - -<p> -For example, suppose that a new method <code>getter()</code> is added -to a <code>CtClass</code> object representing <code>Point</code> -class. Later, the program attempts to compile source code including a -method call to <code>getter()</code> in <code>Point</code> and use the -compiled code as the body of a method, which will be added to another -class <code>Line</code>. If the <code>CtClass</code> object representing -<code>Point</code> is lost, the compiler cannot compile the method call -to <code>getter()</code>. Note that the original class definition does -not include <code>getter()</code>. Therefore, to correctly compile -such a method call, the <code>ClassPool</code> -must contain all the instances of <code>CtClass</code> all the time of -program execution. - -<a name="avoidmemory"> -<h4>Avoid out of memory</h4> -</a> - -<p> -This specification of <code>ClassPool</code> may cause huge memory -consumption if the number of <code>CtClass</code> objects becomes -amazingly large (this rarely happens since Javassist tries to reduce -memory consumption in <a href="#frozenclasses">various ways</a>). -To avoid this problem, you -can explicitly remove an unnecessary <code>CtClass</code> object from -the <code>ClassPool</code>. If you call <code>detach()</code> on a -<code>CtClass</code> object, then that <code>CtClass</code> object is -removed from the <code>ClassPool</code>. For example, - -<ul><pre> -CtClass cc = ... ; -cc.writeFile(); -cc.detach(); -</pre></ul> - -<p>You must not call any method on that -<code>CtClass</code> object after <code>detach()</code> is called. -However, you can call <code>get()</code> on <code>ClassPool</code> -to make a new instance of <code>CtClass</code> representing -the same class. If you call <code>get()</code>, the <code>ClassPool</code> -reads a class file again and newly creates a <code>CtClass</code> -object, which is returned by <code>get()</code>. - -<p> -Another idea is to occasionally replace a <code>ClassPool</code> with -a new one and discard the old one. If an old <code>ClassPool</code> -is garbage collected, the <code>CtClass</code> objects included in -that <code>ClassPool</code> are also garbage collected. -To create a new instance of <code>ClassPool</code>, execute the following -code snippet: - -<ul><pre> -ClassPool cp = new ClassPool(true); -// if needed, append an extra search path by appendClassPath() -</pre></ul> - -<p>This creates a <code>ClassPool</code> object that behaves as the -default <code>ClassPool</code> returned by -<code>ClassPool.getDefault()</code> does. -Note that <code>ClassPool.getDefault()</code> is a singleton factory method -provided for convenience. It creates a <code>ClassPool</code> object in -the same way shown above although it keeps a single instance of -<code>ClassPool</code> and reuses it. -A <code>ClassPool</code> object returned by <code>getDefault()</code> -does not have a special role. <code>getDefault()</code> is a convenience -method. - -<p>Note that <code>new ClassPool(true)</code> is a convenient constructor, -which constructs a <code>ClassPool</code> object and appends the system -search path to it. Calling that constructor is -equivalent to the following code: - -<ul><pre> -ClassPool cp = new ClassPool(); -cp.appendSystemPath(); // or append another path by appendClassPath() -</pre></ul> - -<h4>Cascaded ClassPools</h4> - -<p> -<em>If a program is running on a web application server,</em> -creating multiple instances of <code>ClassPool</code> might be necessary; -an instance of <code>ClassPool</code> should be created -for each class loader (i.e. container). -The program should create a <code>ClassPool</code> object by not calling -<code>getDefault()</code> but a constructor of <code>ClassPool</code>. - -<p> -Multiple <code>ClassPool</code> objects can be cascaded like -<code>java.lang.ClassLoader</code>. For example, - -<ul><pre> -ClassPool parent = ClassPool.getDefault(); -ClassPool child = new ClassPool(parent); -child.insertClassPath("./classes"); -</pre></ul> - -<p> -If <code>child.get()</code> is called, the child <code>ClassPool</code> -first delegates to the parent <code>ClassPool</code>. If the parent -<code>ClassPool</code> fails to find a class file, then the child -<code>ClassPool</code> attempts to find a class file -under the <code>./classes</code> directory. - -<p> -If <code>child.childFirstLookup</code> is true, the child -<code>ClassPool</code> attempts to find a class file before delegating -to the parent <code>ClassPool</code>. For example, - -<ul><pre> -ClassPool parent = ClassPool.getDefault(); -ClassPool child = new ClassPool(parent); -child.appendSystemPath(); // the same class path as the default one. -child.childFirstLookup = true; // changes the behavior of the child. -</pre></ul> - -<h4>Changing a class name for defining a new class</h4> - -<p>A new class can be defined as a copy of an existing class. -The program below does that: - -<ul><pre> -ClassPool pool = ClassPool.getDefault(); -CtClass cc = pool.get("Point"); -cc.setName("Pair"); -</pre></ul> - -<p>This program first obtains the <code>CtClass</code> object for -class <code>Point</code>. Then it calls <code>setName()</code> to -give a new name <code>Pair</code> to that <code>CtClass</code> object. -After this call, all occurrences of the class name in the class -definition represented by that <code>CtClass</code> object are changed -from <code>Point</code> to <code>Pair</code>. The other part of the -class definition does not change. - -<p>Note that <code>setName()</code> in <code>CtClass</code> changes a -record in the <code>ClassPool</code> object. From the implementation -viewpoint, a <code>ClassPool</code> object is a hash table of -<code>CtClass</code> objects. <code>setName()</code> changes -the key associated to the <code>CtClass</code> object in the hash -table. The key is changed from the original class name to the new -class name. - -<p>Therefore, if <code>get("Point")</code> is later called on the -<code>ClassPool</code> object again, then it never returns the -<code>CtClass</code> object that the variable <code>cc</code> refers to. -The <code>ClassPool</code> object reads -a class file -<code>Point.class</code> again and it constructs a new <code>CtClass</code> -object for class <code>Point</code>. -This is because the <code>CtClass</code> object associated with the name -<code>Point</code> does not exist any more. -See the followings: - -<ul><pre> -ClassPool pool = ClassPool.getDefault(); -CtClass cc = pool.get("Point"); -CtClass cc1 = pool.get("Point"); // cc1 is identical to cc. -cc.setName("Pair"); -CtClass cc2 = pool.get("Pair"); // cc2 is identical to cc. -CtClass cc3 = pool.get("Point"); // cc3 is not identical to cc. -</pre></ul> - -<p><code>cc1</code> and <code>cc2</code> refer to the same instance of -<code>CtClass</code> that <code>cc</code> does whereas -<code>cc3</code> does not. Note that, after -<code>cc.setName("Pair")</code> is executed, the <code>CtClass</code> -object that <code>cc</code> and <code>cc1</code> refer to represents -the <code>Pair</code> class. - -<p>The <code>ClassPool</code> object is used to maintain one-to-one -mapping between classes and <code>CtClass</code> objects. Javassist -never allows two distinct <code>CtClass</code> objects to represent -the same class unless two independent <code>ClassPool</code> are created. -This is a significant feature for consistent program -transformation. - -<p>To create another copy of the default instance of -<code>ClassPool</code>, which is returned by -<code>ClassPool.getDefault()</code>, execute the following code -snippet (this code was already <a href="#avoidmemory">shown above</a>): - -<ul><pre> -ClassPool cp = new ClassPool(true); -</pre></ul> - -<p>If you have two <code>ClassPool</code> objects, then you can -obtain, from each <code>ClassPool</code>, a distinct -<code>CtClass</code> object representing the same class file. You can -differently modify these <code>CtClass</code> objects to generate -different versions of the class. - -<h4>Renaming a frozen class for defining a new class</h4> - -<p>Once a <code>CtClass</code> object is converted into a class file -by <code>writeFile()</code> or <code>toBytecode()</code>, Javassist -rejects further modifications of that <code>CtClass</code> object. -Hence, after the <code>CtClass</code> object representing <code>Point</code> -class is converted into a class file, you cannot define <code>Pair</code> -class as a copy of <code>Point</code> since executing <code>setName()</code> -on <code>Point</code> is rejected. -The following code snippet is wrong: - -<ul><pre> -ClassPool pool = ClassPool.getDefault(); -CtClass cc = pool.get("Point"); -cc.writeFile(); -cc.setName("Pair"); // wrong since writeFile() has been called. -</pre></ul> - -<p>To avoid this restriction, you should call <code>getAndRename()</code> -in <code>ClassPool</code>. For example, - -<ul><pre> -ClassPool pool = ClassPool.getDefault(); -CtClass cc = pool.get("Point"); -cc.writeFile(); -CtClass cc2 = pool.getAndRename("Point", "Pair"); -</pre></ul> - -<p>If <code>getAndRename()</code> is called, the <code>ClassPool</code> -first reads <code>Point.class</code> for creating a new <code>CtClass</code> -object representing <code>Point</code> class. However, it renames that -<code>CtClass</code> object from <code>Point</code> to <code>Pair</code> before -it records that <code>CtClass</code> object in a hash table. -Thus <code>getAndRename()</code> -can be executed after <code>writeFile()</code> or <code>toBytecode()</code> -is called on the the <code>CtClass</code> object representing <code>Point</code> -class. - -<p><br> - -<a name="load"> -<h2>3. Class loader</h2> - -<p>If what classes must be modified is known in advance, -the easiest way for modifying the classes is as follows: - -<ul><li>1. Get a <code>CtClass</code> object by calling - <code>ClassPool.get()</code>, - <li>2. Modify it, and - <li>3. Call <code>writeFile()</code> or <code>toBytecode()</code> - on that <code>CtClass</code> object to obtain a modified class file. -</ul> - -<p>If whether a class is modified or not is determined at load time, -the users must make Javassist collaborate with a class loader. -Javassist can be used with a class loader so that bytecode can be -modified at load time. The users of Javassist can define their own -version of class loader but they can also use a class loader provided -by Javassist. - - -<p><br> - -<a name="toclass"> -<h3>3.1 The <code>toClass</code> method in <code>CtClass</code></h3> -</a> - -<p>The <code>CtClass</code> provides a convenience method -<code>toClass()</code>, which requests the context class loader for -the current thread to load the class represented by the <code>CtClass</code> -object. To call this method, the caller must have appropriate permission; -otherwise, a <code>SecurityException</code> may be thrown. - -<p>The following program shows how to use <code>toClass()</code>: - -<ul><pre> -public class Hello { - public void say() { - System.out.println("Hello"); - } -} - -public class Test { - public static void main(String[] args) throws Exception { - ClassPool cp = ClassPool.getDefault(); - CtClass cc = cp.get("Hello"); - CtMethod m = cc.getDeclaredMethod("say"); - m.insertBefore("{ System.out.println(\"Hello.say():\"); }"); - Class c = cc.toClass(); - Hello h = (Hello)c.newInstance(); - h.say(); - } -} -</pre></ul> - -<p><code>Test.main()</code> inserts a call to <code>println()</code> -in the method body of <code>say()</code> in <code>Hello</code>. Then -it constructs an instance of the modified <code>Hello</code> class -and calls <code>say()</code> on that instance. - -<p>Note that the program above depends on the fact that the -<code>Hello</code> class is never loaded before <code>toClass()</code> -is invoked. If not, the JVM would load the original -<code>Hello</code> class before <code>toClass()</code> requests to -load the modified <code>Hello</code> class. Hence loading the -modified <code>Hello</code> class would be failed -(<code>LinkageError</code> is thrown). For example, if -<code>main()</code> in <code>Test</code> is something like this: - -<ul><pre> -public static void main(String[] args) throws Exception { - Hello orig = new Hello(); - ClassPool cp = ClassPool.getDefault(); - CtClass cc = cp.get("Hello"); - : -} -</pre></ul> - -<p>then the original <code>Hello</code> class is loaded at the first -line of <code>main</code> and the call to <code>toClass()</code> -throws an exception since the class loader cannot load two different -versions of the <code>Hello</code> class at the same time. - -<p><em>If the program is running on some application server such as -JBoss and Tomcat,</em> the context class loader used by -<code>toClass()</code> might be inappropriate. In this case, you -would see an unexpected <code>ClassCastException</code>. To avoid -this exception, you must explicitly give an appropriate class loader -to <code>toClass()</code>. For example, if <code>bean</code> is your -session bean object, then the following code: - -<ul><pre>CtClass cc = ...; -Class c = cc.toClass(bean.getClass().getClassLoader()); -</pre></ul> - -<p>would work. You should give <code>toClass()</code> the class loader -that has loaded your program (in the above example, the class of -the <code>bean</code> object). - -<p><code>toClass()</code> is provided for convenience. If you need -more complex functionality, you should write your own class loader. - -<p><br> - -<h3>3.2 Class loading in Java</h3> - -<p>In Java, multiple class loaders can coexist and -each class loader creates its own name space. -Different class loaders can load different class files with the -same class name. The loaded two classes are regarded as different -ones. This feature enables us to run multiple application programs -on a single JVM even if these programs include different classes -with the same name. - -<ul> -<b>Note:</b> The JVM does not allow dynamically reloading a class. -Once a class loader loads a class, it cannot reload a modified -version of that class during runtime. Thus, you cannot alter -the definition of a class after the JVM loads it. -However, the JPDA (Java Platform Debugger Architecture) provides -limited ability for reloading a class. -See <a href="#hotswap">Section 3.6</a>. -</ul> - -<p>If the same class file is loaded by two distinct class loaders, -the JVM makes two distinct classes with the same name and definition. -The two classes are regarded as different ones. -Since the two classes are not identical, an instance of one class is -not assignable to a variable of the other class. The cast operation -between the two classes fails -and throws a <em><code>ClassCastException</code></em>. - -<p>For example, the following code snippet throws an exception: - -<ul><pre> -MyClassLoader myLoader = new MyClassLoader(); -Class clazz = myLoader.loadClass("Box"); -Object obj = clazz.newInstance(); -Box b = (Box)obj; // this always throws ClassCastException. -</pre></ul> - -<p> -The <code>Box</code> class is loaded by two class loaders. -Suppose that a class loader CL loads a class including this code snippet. -Since this code snippet refers to <code>MyClassLoader</code>, -<code>Class</code>, <code>Object</code>, and <code>Box</code>, -CL also loads these classes (unless it delegates to another class loader). -Hence the type of the variable <code>b</code> is the <code>Box</code> -class loaded by CL. -On the other hand, <code>myLoader</code> also loads the <code>Box</code> -class. The object <code>obj</code> is an instance of -the <code>Box</code> class loaded by <code>myLoader</code>. -Therefore, the last statement always throws a -<code>ClassCastException</code> since the class of <code>obj</code> is -a different verison of the <code>Box</code> class from one used as the -type of the variable <code>b</code>. - -<p>Multiple class loaders form a tree structure. -Each class loader except the bootstrap loader has a -parent class loader, which has normally loaded the class of that child -class loader. Since the request to load a class can be delegated along this -hierarchy of class loaders, a class may be loaded by a class loader that -you do not request the class loading. -Therefore, the class loader that has been requested to load a class C -may be different from the loader that actually loads the class C. -For distinction, we call the former loader <em>the initiator of C</em> -and we call the latter loader <em>the real loader of C</em>. - -<p> -Furthermore, if a class loader CL requested to load a class C -(the initiator of C) delegates -to the parent class loader PL, then the class loader CL is never requested -to load any classes referred to in the definition of the class C. -CL is not the initiator of those classes. -Instead, the parent class loader PL becomes their initiators -and it is requested to load them. -<em>The classes that the definition of a class C referes to are loaded by -the real loader of C.</em> - -<p>To understand this behavior, let's consider the following example. - -<ul><pre> -public class Point { // loaded by PL - private int x, y; - public int getX() { return x; } - : -} - -public class Box { // the initiator is L but the real loader is PL - private Point upperLeft, size; - public int getBaseX() { return upperLeft.x; } - : -} - -public class Window { // loaded by a class loader L - private Box box; - public int getBaseX() { return box.getBaseX(); } -}</pre></ul> - -<p>Suppose that a class <code>Window</code> is loaded by a class loader L. -Both the initiator and the real loader of <code>Window</code> are L. -Since the definition of <code>Window</code> refers to <code>Box</code>, -the JVM will request L to load <code>Box</code>. -Here, suppose that L delegates this task to the parent class loader PL. -The initiator of <code>Box</code> is L but the real loader is PL. -In this case, the initiator of <code>Point</code> is not L but PL -since it is the same as the real loader of <code>Box</code>. -Thus L is never requested to load <code>Point</code>. - -<p>Next, let's consider a slightly modified example. - -<ul><pre> -public class Point { - private int x, y; - public int getX() { return x; } - : -} - -public class Box { // the initiator is L but the real loader is PL - private Point upperLeft, size; - public Point getSize() { return size; } - : -} - -public class Window { // loaded by a class loader L - private Box box; - public boolean widthIs(int w) { - Point p = box.getSize(); - return w == p.getX(); - } -}</pre></ul> - -<p>Now, the definition of <code>Window</code> also refers to -<code>Point</code>. In this case, the class loader L must -also delegate to PL if it is requested to load <code>Point</code>. -<em>You must avoid having two class loaders doubly load the same -class.</em> One of the two loaders must delegate to -the other. - -<p> -If L does not delegate to PL when <code>Point</code> -is loaded, <code>widthIs()</code> would throw a ClassCastException. -Since the real loader of <code>Box</code> is PL, -<code>Point</code> referred to in <code>Box</code> is also loaded by PL. -Therefore, the resulting value of <code>getSize()</code> -is an instance of <code>Point</code> loaded by PL -whereas the type of the variable <code>p</code> in <code>widthIs()</code> -is <code>Point</code> loaded by L. -The JVM regards them as distinct types and thus it throws an exception -because of type mismatch. - -<p>This behavior is somewhat inconvenient but necessary. -If the following statement: - -<ul><pre> -Point p = box.getSize(); -</pre></ul> - -<p>did not throw an exception, -then the programmer of <code>Window</code> could break the encapsulation -of <code>Point</code> objects. -For example, the field <code>x</code> -is private in <code>Point</code> loaded by PL. -However, the <code>Window</code> class could -directly access the value of <code>x</code> -if L loads <code>Point</code> with the following definition: - -<ul><pre> -public class Point { - public int x, y; // not private - public int getX() { return x; } - : -} -</pre></ul> - -<p> -For more details of class loaders in Java, the following paper would -be helpful: - -<ul>Sheng Liang and Gilad Bracha, -"Dynamic Class Loading in the Java Virtual Machine", -<br><i>ACM OOPSLA'98</i>, pp.36-44, 1998.</ul> - -<p><br> - -<h3>3.3 Using <code>javassist.Loader</code></h3> - -<p>Javassist provides a class loader -<code>javassist.Loader</code>. This class loader uses a -<code>javassist.ClassPool</code> object for reading a class file. - -<p>For example, <code>javassist.Loader</code> can be used for loading -a particular class modified with Javassist. - -<ul><pre> -import javassist.*; -import test.Rectangle; - -public class Main { - public static void main(String[] args) throws Throwable { - ClassPool pool = ClassPool.getDefault(); - Loader cl = new Loader(pool); - - CtClass ct = pool.get("test.Rectangle"); - ct.setSuperclass(pool.get("test.Point")); - - Class c = cl.loadClass("test.Rectangle"); - Object rect = c.newInstance(); - : - } -} -</pre></ul> - -<p>This program modifies a class <code>test.Rectangle</code>. The -superclass of <code>test.Rectangle</code> is set to a -<code>test.Point</code> class. Then this program loads the modified -class, and creates a new instance of the -<code>test.Rectangle</code> class. - -<p>If the users want to modify a class on demand when it is loaded, -the users can add an event listener to a <code>javassist.Loader</code>. -The added event listener is -notified when the class loader loads a class. -The event-listener class must implement the following interface: - -<ul><pre>public interface Translator { - public void start(ClassPool pool) - throws NotFoundException, CannotCompileException; - public void onLoad(ClassPool pool, String classname) - throws NotFoundException, CannotCompileException; -}</pre></ul> - -<p>The method <code>start()</code> is called when this event listener -is added to a <code>javassist.Loader</code> object by -<code>addTranslator()</code> in <code>javassist.Loader</code>. The -method <code>onLoad()</code> is called before -<code>javassist.Loader</code> loads a class. <code>onLoad()</code> -can modify the definition of the loaded class. - -<p>For example, the following event listener changes all classes -to public classes just before they are loaded. - -<ul><pre>public class MyTranslator implements Translator { - void start(ClassPool pool) - throws NotFoundException, CannotCompileException {} - void onLoad(ClassPool pool, String classname) - throws NotFoundException, CannotCompileException - { - CtClass cc = pool.get(classname); - cc.setModifiers(Modifier.PUBLIC); - } -}</pre></ul> - -<p>Note that <code>onLoad()</code> does not have to call -<code>toBytecode()</code> or <code>writeFile()</code> since -<code>javassist.Loader</code> calls these methods to obtain a class -file. - -<p>To run an application class <code>MyApp</code> with a -<code>MyTranslator</code> object, write a main class as following: - -<ul><pre> -import javassist.*; - -public class Main2 { - public static void main(String[] args) throws Throwable { - Translator t = new MyTranslator(); - ClassPool pool = ClassPool.getDefault(); - Loader cl = new Loader(); - cl.addTranslator(pool, t); - cl.run("MyApp", args); - } -} -</pre></ul> - -<p>To run this program, do: - -<ul><pre> -% java Main2 <i>arg1</i> <i>arg2</i>... -</pre></ul> - -<p>The class <code>MyApp</code> and the other application classes -are translated by <code>MyTranslator</code>. - -<p>Note that <em>application</em> classes like <code>MyApp</code> cannot -access the <em>loader</em> classes such as <code>Main2</code>, -<code>MyTranslator</code>, and <code>ClassPool</code> because they -are loaded by different loaders. The application classes are loaded -by <code>javassist.Loader</code> whereas the loader classes such as -<code>Main2</code> are by the default Java class loader. - -<p><code>javassist.Loader</code> searches for classes in a different -order from <code>java.lang.ClassLoader</code>. -<code>ClassLoader</code> first delegates the loading operations to -the parent class loader and then attempts to load the classes -only if the parent class loader cannot find them. -On the other hand, -<code>javassist.Loader</code> attempts -to load the classes before delegating to the parent class loader. -It delegates only if: - -<ul><li>the classes are not found by calling <code>get()</code> on -a <code>ClassPool</code> object, or - -<p><li>the classes have been specified by using -<code>delegateLoadingOf()</code> -to be loaded by the parent class loader. -</ul> - -<p>This search order allows loading modified classes by Javassist. -However, it delegates to the parent class loader if it fails -to find modified classes for some reason. Once a class is loaded by -the parent class loader, the other classes referred to in that class will be -also loaded by the parent class loader and thus they are never modified. -Recall that all the classes referred to in a class C are loaded by the -real loader of C. -<em>If your program fails to load a modified class,</em> you should -make sure whether all the classes using that class have been loaded by -<code>javassist.Loader</code>. - -<p><br> - -<h3>3.4 Writing a class loader</h3> - -<p>A simple class loader using Javassist is as follows: - -<ul><pre>import javassist.*; - -public class SampleLoader extends ClassLoader { - /* Call MyApp.main(). - */ - public static void main(String[] args) throws Throwable { - SampleLoader s = new SampleLoader(); - Class c = s.loadClass("MyApp"); - c.getDeclaredMethod("main", new Class[] { String[].class }) - .invoke(null, new Object[] { args }); - } - - private ClassPool pool; - - public SampleLoader() throws NotFoundException { - pool = new ClassPool(); - pool.insertClassPath("./class"); // <em>MyApp.class must be there.</em> - } - - /* Finds a specified class. - * The bytecode for that class can be modified. - */ - protected Class findClass(String name) throws ClassNotFoundException { - try { - CtClass cc = pool.get(name); - // <em>modify the CtClass object here</em> - byte[] b = cc.toBytecode(); - return defineClass(name, b, 0, b.length); - } catch (NotFoundException e) { - throw new ClassNotFoundException(); - } catch (IOException e) { - throw new ClassNotFoundException(); - } catch (CannotCompileException e) { - throw new ClassNotFoundException(); - } - } -}</pre></ul> - -<p>The class <code>MyApp</code> is an application program. -To execute this program, first put the class file under the -<code>./class</code> directory, which must <em>not</em> be included -in the class search path. Otherwise, <code>MyApp.class</code> would -be loaded by the default system class loader, which is the parent -loader of <code>SampleLoader</code>. -The directory name <code>./class</code> is specified by -<code>insertClassPath()</code> in the constructor. -You can choose a different name instead of <code>./class</code> if you want. -Then do as follows: - -<ul><code>% java SampleLoader</code></ul> - -<p>The class loader loads the class <code>MyApp</code> -(<code>./class/MyApp.class</code>) and calls -<code>MyApp.main()</code> with the command line parameters. - -<p>This is the simplest way of using Javassist. However, if you write -a more complex class loader, you may need detailed knowledge of -Java's class loading mechanism. For example, the program above puts the -<code>MyApp</code> class in a name space separated from the name space -that the class <code>SampleLoader</code> belongs to because the two -classes are loaded by different class loaders. -Hence, the -<code>MyApp</code> class cannot directly access the class -<code>SampleLoader</code>. - -<p><br> - -<h3>3.5 Modifying a system class</h3> - -<p>The system classes like <code>java.lang.String</code> cannot be -loaded by a class loader other than the system class loader. -Therefore, <code>SampleLoader</code> or <code>javassist.Loader</code> -shown above cannot modify the system classes at loading time. - -<p>If your application needs to do that, the system classes must be -<em>statically</em> modified. For example, the following program -adds a new field <code>hiddenValue</code> to <code>java.lang.String</code>: - -<ul><pre>ClassPool pool = ClassPool.getDefault(); -CtClass cc = pool.get("java.lang.String"); -CtField f = new CtField(CtClass.intType, "hiddenValue", cc); -f.setModifiers(Modifier.PUBLIC); -cc.addField(f); -cc.writeFile(".");</pre></ul> - -<p>This program produces a file <code>"./java/lang/String.class"</code>. - -<p>To run your program <code>MyApp</code> -with this modified <code>String</code> class, do as follows: - -<ul><pre> -% java -Xbootclasspath/p:. MyApp <i>arg1</i> <i>arg2</i>... -</pre></ul> - -<p>Suppose that the definition of <code>MyApp</code> is as follows: - -<ul><pre>public class MyApp { - public static void main(String[] args) throws Exception { - System.out.println(String.class.getField("hiddenValue").getName()); - } -}</pre></ul> - -<p>If the modified <code>String</code> class is correctly loaded, -<code>MyApp</code> prints <code>hiddenValue</code>. - -<p><i>Note: Applications that use this technique for the purpose of -overriding a system class in <code>rt.jar</code> should not be -deployed as doing so would contravene the Java 2 Runtime Environment -binary code license.</i> - -<p><br> - -<a name="hotswap"> -<h3>3.6 Reloading a class at runtime</h3></a> - -<p>If the JVM is launched with the JPDA (Java Platform Debugger -Architecture) enabled, a class is dynamically reloadable. After the -JVM loads a class, the old version of the class definition can be -unloaded and a new one can be reloaded again. That is, the definition -of that class can be dynamically modified during runtime. However, -the new class definition must be somewhat compatible to the old one. -<em>The JVM does not allow schema changes between the two versions.</em> -They have the same set of methods and fields. - -<p>Javassist provides a convenient class for reloading a class at runtime. -For more information, see the API documentation of -<code>javassist.tools.HotSwapper</code>. - -<p><br> - -<a href="tutorial2.html">Next page</a> - -<hr> -Java(TM) is a trademark of Sun Microsystems, Inc.<br> -Copyright (C) 2000-2015 by Shigeru Chiba, All rights reserved. -</body> -</html> diff --git a/tutorial/tutorial2.html b/tutorial/tutorial2.html deleted file mode 100644 index 04afbd9c..00000000 --- a/tutorial/tutorial2.html +++ /dev/null @@ -1,1633 +0,0 @@ -<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="tutorial.html">Previous page</a></div> -<div align="right"><a href="tutorial3.html">Next page</a></div> - -<p> -<a href="#intro">4. Introspection and customization</a> -<ul> -<li><a href="#before">Inserting source text at the beginning/end of a method body</a> -<br><li><a href="#alter">Altering a method body</a> -<br><li><a href="#add">Adding a new method or field</a> -<br><li><a href="#runtime">Runtime support classes</a> -<br><li><a href="#annotation">Annotations</a> -<br><li><a href="#import">Import</a> -<br><li><a href="#limit">Limitations</a> -</ul> - -<p><br> - -<a name="intro"> -<h2>4. Introspection and customization</h2> - -<p><code>CtClass</code> provides methods for introspection. The -introspective ability of Javassist is compatible with that of -the Java reflection API. <code>CtClass</code> provides -<code>getName()</code>, <code>getSuperclass()</code>, -<code>getMethods()</code>, and so on. -<code>CtClass</code> also provides methods for modifying a class -definition. It allows to add a new field, constructor, and method. -Instrumenting a method body is also possible. - -<p> -Methods are represented by <code>CtMethod</code> objects. -<code>CtMethod</code> provides several methods for modifying -the definition of the method. Note that if a method is inherited -from a super class, then -the same <code>CtMethod</code> object -that represents the inherited method represents the method declared -in that super class. -A <code>CtMethod</code> object corresponds to every method declaration. - -<p> -For example, if class <code>Point</code> declares method <code>move()</code> -and a subclass <code>ColorPoint</code> of <code>Point</code> does -not override <code>move()</code>, the two <code>move()</code> methods -declared in <code>Point</code> and inherited in <code>ColorPoint</code> -are represented by the identical <code>CtMethod</code> object. -If the method definition represented by this -<code>CtMethod</code> object is modified, the modification is -reflected on both the methods. -If you want to modify only the <code>move()</code> method in -<code>ColorPoint</code>, you first have to add to <code>ColorPoint</code> -a copy of the <code>CtMethod</code> object representing <code>move()</code> -in <code>Point</code>. A copy of the the <code>CtMethod</code> object -can be obtained by <code>CtNewMethod.copy()</code>. - - -<p><hr width="40%"> - -<ul> -Javassist does not allow to remove a method or field, but it allows -to change the name. So if a method is not necessary any more, it should be -renamed and changed to be a private method by calling -<code>setName()</code> -and <code>setModifiers()</code> declared in <code>CtMethod</code>. - -<p>Javassist does not allow to add an extra parameter to an existing -method, either. Instead of doing that, a new method receiving the -extra parameter as well as the other parameters should be added to the -same class. For example, if you want to add an extra <code>int</code> -parameter <code>newZ</code> to a method: - -<ul><pre>void move(int newX, int newY) { x = newX; y = newY; }</pre></ul> - -<p>in a <code>Point</code> class, then you should add the following -method to the <code>Point</code> class: - -<ul><pre>void move(int newX, int newY, int newZ) { - // do what you want with newZ. - move(newX, newY); -}</pre></ul> - -</ul> - -<p><hr width="40%"> - -<p>Javassist also provides low-level API for directly editing a raw -class file. For example, <code>getClassFile()</code> in -<code>CtClass</code> returns a <code>ClassFile</code> object -representing a raw class file. <code>getMethodInfo()</code> in -<code>CtMethod</code> returns a <code>MethodInfo</code> object -representing a <code>method_info</code> structure included in a class -file. The low-level API uses the vocabulary from the Java Virtual -machine specification. The users must have the knowledge about class -files and bytecode. For more details, the users should see the -<a href="tutorial3.html#intro"><code>javassist.bytecode</code> package</a>. - -<p>The class files modified by Javassist requires the -<code>javassist.runtime</code> package for runtime support -only if some special identifiers starting with <code>$</code> -are used. Those special identifiers are described below. -The class files modified without those special identifiers -do not need the <code>javassist.runtime</code> package or any -other Javassist packages at runtime. -For more details, see the API documentation -of the <code>javassist.runtime</code> package. - -<p><br> - -<a name="before"> -<h3>4.1 Inserting source text at the beginning/end of a method body</h3> - -<p><code>CtMethod</code> and <code>CtConstructor</code> provide -methods <code>insertBefore()</code>, <code>insertAfter()</code>, and -<code>addCatch()</code>. They are used for inserting a code fragment -into the body of an existing method. The users can specify those code -fragments with <em>source text</em> written in Java. -Javassist includes a simple Java compiler for processing source -text. It receives source text -written in Java and compiles it into Java bytecode, which will be -<em>inlined</em> into a method body. - -<p> -Inserting a code fragment at the position specified by a line number -is also possible -(if the line number table is contained in the class file). -<code>insertAt()</code> in <code>CtMethod</code> and -<code>CtConstructor</code> takes source text and a line number in the source -file of the original class definition. -It compiles the source text and inserts the compiled code at the line number. - -<p>The methods <code>insertBefore()</code>, <code>insertAfter()</code>, -<code>addCatch()</code>, and <code>insertAt()</code> -receive a <code>String</code> object representing -a statement or a block. A statement is a single control structure like -<code>if</code> and <code>while</code> or an expression ending with -a semi colon (<code>;</code>). A block is a set of -statements surrounded with braces <code>{}</code>. -Hence each of the following lines is an example of valid statement or block: - -<ul><pre>System.out.println("Hello"); -{ System.out.println("Hello"); } -if (i < 0) { i = -i; } -</pre></ul> - -<p>The statement and the block can refer to fields and methods. -They can also refer to the parameters -to the method that they are inserted into -if that method was compiled with the -g option -(to include a local variable attribute in the class file). -Otherwise, they must access the method parameters through the special -variables <code>$0</code>, <code>$1</code>, <code>$2</code>, ... described -below. -<em>Accessing local variables declared in the method is not allowed</em> -although declaring a new local variable in the block is allowed. -However, <code>insertAt()</code> allows the statement and the block -to access local variables -if these variables are available at the specified line number -and the target method was compiled with the -g option. - - -<!-- -<p><center><table border=8 cellspacing=0 bordercolor="#cfcfcf"> -<tr><td bgcolor="#cfcfcf"> -<b>Tip:</b> -<br>    Local variables are not accessible.   -</td></tr> -</table></center> ---> - -<p>The <code>String</code> object passed to the methods -<code>insertBefore()</code>, <code>insertAfter()</code>, -<code>addCatch()</code>, and <code>insertAt()</code> are compiled by -the compiler included in Javassist. -Since the compiler supports language extensions, -several identifiers starting with <code>$</code> -have special meaning: - -<ul><table border=0> -<tr> -<td><code>$0</code>, <code>$1</code>, <code>$2</code>, ...    </td> -<td><code>this</code> and actual parameters</td> -</tr> - -<tr> -<td><code>$args</code></td> -<td>An array of parameters. -The type of <code>$args</code> is <code>Object[]</code>. -</td> -</tr> - -<tr> -<td><code>$$</code></td> -<td rowspan=2>All actual parameters.<br> -For example, <code>m($$)</code> is equivalent to -<code>m($1,$2,</code>...<code>)</code></td> -</tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$cflow(</code>...<code>)</code></td> -<td><code>cflow</code> variable</td> -</tr> - -<tr> -<td><code>$r</code></td> -<td>The result type. It is used in a cast expression.</td> -</tr> - -<tr> -<td><code>$w</code></td> -<td>The wrapper type. It is used in a cast expression.</td> -</tr> - -<tr> -<td><code>$_</code></td> -<td>The resulting value</td> -</tr> - -<tr> -<td><code>$sig</code></td> -<td>An array of <code>java.lang.Class</code> objects representing -the formal parameter types. -</td> -</tr> - -<tr> -<td><code>$type</code></td> -<td>A <code>java.lang.Class</code> object representing -the formal result type.</td> -</tr> - -<tr> -<td><code>$class</code></td> -<td>A <code>java.lang.Class</code> object representing -the class currently edited.</td> -</tr> - -</table> -</ul> - -<h4>$0, $1, $2, ...</h4> - -<p>The parameters passed to the target method -are accessible with -<code>$1</code>, <code>$2</code>, ... instead of -the original parameter names. -<code>$1</code> represents the -first parameter, <code>$2</code> represents the second parameter, and -so on. The types of those variables are identical to the parameter -types. -<code>$0</code> is -equivalent to <code>this</code>. If the method is static, -<code>$0</code> is not available. - -<p>These variables are used as following. Suppose that a class -<code>Point</code>: - -<pre><ul>class Point { - int x, y; - void move(int dx, int dy) { x += dx; y += dy; } -} -</ul></pre> - -<p>To print the values of <code>dx</code> and <code>dy</code> -whenever the method <code>move()</code> is called, execute this -program: - -<ul><pre>ClassPool pool = ClassPool.getDefault(); -CtClass cc = pool.get("Point"); -CtMethod m = cc.getDeclaredMethod("move"); -m.insertBefore("{ System.out.println($1); System.out.println($2); }"); -cc.writeFile(); -</pre></ul> - -<p>Note that the source text passed to <code>insertBefore()</code> is -surrounded with braces <code>{}</code>. -<code>insertBefore()</code> accepts only a single statement or a block -surrounded with braces. - -<p>The definition of the class <code>Point</code> after the -modification is like this: - -<pre><ul>class Point { - int x, y; - void move(int dx, int dy) { - { System.out.println(dx); System.out.println(dy); } - x += dx; y += dy; - } -} -</ul></pre> - -<p><code>$1</code> and <code>$2</code> are replaced with -<code>dx</code> and <code>dy</code>, respectively. - -<p><code>$1</code>, <code>$2</code>, <code>$3</code> ... are -updatable. If a new value is assigend to one of those variables, -then the value of the parameter represented by that variable is -also updated. - - -<h4>$args</h4> - -<p>The variable <code>$args</code> represents an array of all the -parameters. The type of that variable is an array of class -<code>Object</code>. If a parameter type is a primitive type such as -<code>int</code>, then the parameter value is converted into a wrapper -object such as <code>java.lang.Integer</code> to store in -<code>$args</code>. Thus, <code>$args[0]</code> is equivalent to -<code>$1</code> unless the type of the first parameter is a primitive -type. Note that <code>$args[0]</code> is not equivalent to -<code>$0</code>; <code>$0</code> represents <code>this</code>. - -<p>If an array of <code>Object</code> is assigned to -<code>$args</code>, then each element of that array is -assigned to each parameter. If a parameter type is a primitive -type, the type of the corresponding element must be a wrapper type. -The value is converted from the wrapper type to the primitive type -before it is assigned to the parameter. - -<h4>$$</h4> - -<p>The variable <code>$$</code> is abbreviation of a list of -all the parameters separated by commas. -For example, if the number of the parameters -to method <code>move()</code> is three, then - -<ul><pre>move($$)</pre></ul> - -<p>is equivalent to this: - -<ul><pre>move($1, $2, $3)</pre></ul> - -<p>If <code>move()</code> does not take any parameters, -then <code>move($$)</code> is -equivalent to <code>move()</code>. - -<p><code>$$</code> can be used with another method. -If you write an expression: - -<ul><pre>exMove($$, context)</pre></ul> - -<p>then this expression is equivalent to: - -<ul><pre>exMove($1, $2, $3, context)</pre></ul> - -<p>Note that <code>$$</code> enables generic notation of method call -with respect to the number of parameters. -It is typically used with <code>$proceed</code> shown later. - -<h4>$cflow</h4> - -<p><code>$cflow</code> means "control flow". -This read-only variable returns the depth of the recursive calls -to a specific method. - -<p>Suppose that the method shown below is represented by a -<code>CtMethod</code> object <code>cm</code>: - -<ul><pre>int fact(int n) { - if (n <= 1) - return n; - else - return n * fact(n - 1); -}</pre></ul> - -<p>To use <code>$cflow</code>, first declare that <code>$cflow</code> -is used for monitoring calls to the method <code>fact()</code>: - -<ul><pre>CtMethod cm = ...; -cm.useCflow("fact");</pre></ul> - -<p>The parameter to <code>useCflow()</code> is the identifier of the -declared <code>$cflow</code> variable. Any valid Java name can be -used as the identifier. Since the identifier can also include -<code>.</code> (dot), for example, <code>"my.Test.fact"</code> -is a valid identifier. - -<p>Then, <code>$cflow(fact)</code> represents the depth of the -recursive calls to the method specified by <code>cm</code>. The value -of <code>$cflow(fact)</code> is 0 (zero) when the method is -first called whereas it is 1 when the method is recursively called -within the method. For example, - -<ul><pre> -cm.insertBefore("if ($cflow(fact) == 0)" - + " System.out.println(\"fact \" + $1);"); -</pre></ul> - -<p>translates the method <code>fact()</code> so that it shows the -parameter. Since the value of <code>$cflow(fact)</code> is checked, -the method <code>fact()</code> does not show the parameter if it is -recursively called within <code>fact()</code>. - -<p>The value of <code>$cflow</code> is the number of stack frames -associated with the specified method <code>cm</code> -under the current topmost -stack frame for the current thread. <code>$cflow</code> is also -accessible within a method different from the specified method -<code>cm</code>. - -<h4>$r</h4> - -<p><code>$r</code> represents the result type (return type) of the method. -It must be used as the cast type in a cast expression. -For example, this is a typical use: - -<ul><pre>Object result = ... ; -$_ = ($r)result;</pre></ul> - -<p>If the result type is a primitive type, then <code>($r)</code> -follows special semantics. First, if the operand type of the cast -expression is a primitive type, <code>($r)</code> works as a normal -cast operator to the result type. -On the other hand, if the operand type is a wrapper type, -<code>($r)</code> converts from the wrapper type to the result type. -For example, if the result type is <code>int</code>, then -<code>($r)</code> converts from <code>java.lang.Integer</code> to -<code>int</code>. - -<p>If the result type is <code>void</code>, then -<code>($r)</code> does not convert a type; it does nothing. -However, if the operand is a call to a <code>void</code> method, -then <code>($r)</code> results in <code>null</code>. For example, -if the result type is <code>void</code> and -<code>foo()</code> is a <code>void</code> method, then - -<ul><pre>$_ = ($r)foo();</pre></ul> - -<p>is a valid statement. - -<p>The cast operator <code>($r)</code> is also useful in a -<code>return</code> statement. Even if the result type is -<code>void</code>, the following <code>return</code> statement is valid: - -<ul><pre>return ($r)result;</pre></ul> - -<p>Here, <code>result</code> is some local variable. -Since <code>($r)</code> is specified, the resulting value is -discarded. -This <code>return</code> statement is regarded as the equivalent -of the <code>return</code> statement without a resulting value: - -<ul><pre>return;</pre></ul> - -<h4>$w</h4> - -<p><code>$w</code> represents a wrapper type. -It must be used as the cast type in a cast expression. -<code>($w)</code> converts from a primitive type to the corresponding -wrapper type. - -The following code is an example: - -<ul><pre>Integer i = ($w)5;</pre></ul> - -<p>The selected wrapper type depends on the type of the expression -following <code>($w)</code>. If the type of the expression is -<code>double</code>, then the wrapper type is <code>java.lang.Double</code>. - -<p>If the type of the expression following <code>($w)</code> is not -a primitive type, then <code>($w)</code> does nothing. - -<h4>$_</h4> - -<p><code>insertAfter()</code> in <code>CtMethod</code> and -<code>CtConstructor</code> inserts the -compiled code at the end of the method. In the statement given to -<code>insertAfter()</code>, not only the variables shown above such as -<code>$0</code>, <code>$1</code>, ... but also <code>$_</code> is -available. - -<p>The variable <code>$_</code> represents the resulting value of the -method. The type of that variable is the type of the result type (the -return type) of the method. If the result type is <code>void</code>, -then the type of <code>$_</code> is <code>Object</code> and the value -of <code>$_</code> is <code>null</code>. - -<p>Although the compiled code inserted by <code>insertAfter()</code> -is executed just before the control normally returns from the method, -it can be also executed when an exception is thrown from the method. -To execute it when an exception is thrown, the second parameter -<code>asFinally</code> to <code>insertAfter()</code> must be -<code>true</code>. - -<p>If an exception is thrown, the compiled code inserted by -<code>insertAfter()</code> is executed as a <code>finally</code> -clause. The value of <code>$_</code> is <code>0</code> or -<code>null</code> in the compiled code. After the execution of the -compiled code terminates, the exception originally thrown is re-thrown -to the caller. Note that the value of <code>$_</code> is never thrown -to the caller; it is rather discarded. - -<h4>$sig</h4> - -<p>The value of <code>$sig</code> is an array of -<code>java.lang.Class</code> objects that represent the formal -parameter types in declaration order. - -<h4>$type</h4> - -<p>The value of <code>$type</code> is an <code>java.lang.Class</code> -object representing the formal type of the result value. This -variable refers to <code>Void.class</code> if this is a constructor. - -<h4>$class</h4> - -<p>The value of <code>$class</code> is an <code>java.lang.Class</code> -object representing the class in which the edited method is declared. -This represents the type of <code>$0</code>. - -<h4>addCatch()</h4> - -<p><code>addCatch()</code> inserts a code fragment into a method body -so that the code fragment is executed when the method body throws -an exception and the control returns to the caller. In the source -text representing the inserted code fragment, the exception value -is referred to with the special variable <code>$e</code>. - -<p>For example, this program: - -<ul><pre> -CtMethod m = ...; -CtClass etype = ClassPool.getDefault().get("java.io.IOException"); -m.addCatch("{ System.out.println($e); throw $e; }", etype); -</pre></ul> - -<p>translates the method body represented by <code>m</code> into -something like this: - -<ul><pre> -try { - <font face="serif"><em>the original method body</em></font> -} -catch (java.io.IOException e) { - System.out.println(e); - throw e; -} -</pre></ul> - -<p>Note that the inserted code fragment must end with a -<code>throw</code> or <code>return</code> statement. - -<p><br> - -<a name="alter"> -<h3>4.2 Altering a method body</h3> - -<p><code>CtMethod</code> and <code>CtConstructor</code> provide -<code>setBody()</code> for substituting a whole -method body. They compile the given source text into Java bytecode -and substitutes it for the original method body. If the given source -text is <code>null</code>, the substituted body includes only a -<code>return</code> statement, which returns zero or null unless the -result type is <code>void</code>. - -<p>In the source text given to <code>setBody()</code>, the identifiers -starting with <code>$</code> have special meaning - -<ul><table border=0> -<tr> -<td><code>$0</code>, <code>$1</code>, <code>$2</code>, ...    </td> -<td><code>this</code> and actual parameters</td> -</tr> - -<tr> -<td><code>$args</code></td> -<td>An array of parameters. -The type of <code>$args</code> is <code>Object[]</code>. -</td> -</tr> - -<tr> -<td><code>$$</code></td> -<td>All actual parameters.<br> -</tr> - -<tr> -<td><code>$cflow(</code>...<code>)</code></td> -<td><code>cflow</code> variable</td> -</tr> - -<tr> -<td><code>$r</code></td> -<td>The result type. It is used in a cast expression.</td> -</tr> - -<tr> -<td><code>$w</code></td> -<td>The wrapper type. It is used in a cast expression.</td> -</tr> - -<tr> -<td><code>$sig</code></td> -<td>An array of <code>java.lang.Class</code> objects representing -the formal parameter types. -</td> -</tr> - -<tr> -<td><code>$type</code></td> -<td>A <code>java.lang.Class</code> object representing -the formal result type.</td> -</tr> - -<tr> -<td><code>$class</code></td> -<td rowspan=2>A <code>java.lang.Class</code> object representing -the class that declares the method<br> -currently edited (the type of $0).</td> -</tr> - -<tr><td> </td></tr> - -</table> -</ul> - -Note that <code>$_</code> is not available. - -<h4>Substituting source text for an existing expression</h4> - -<p>Javassist allows modifying only an expression included in a method body. -<code>javassist.expr.ExprEditor</code> is a class -for replacing an expression in a method body. -The users can define a subclass of <code>ExprEditor</code> -to specify how an expression is modified. - -<p>To run an <code>ExprEditor</code> object, the users must -call <code>instrument()</code> in <code>CtMethod</code> or -<code>CtClass</code>. - -For example, - -<ul><pre> -CtMethod cm = ... ; -cm.instrument( - new ExprEditor() { - public void edit(MethodCall m) - throws CannotCompileException - { - if (m.getClassName().equals("Point") - && m.getMethodName().equals("move")) - m.replace("{ $1 = 0; $_ = $proceed($$); }"); - } - }); -</pre></ul> - -<p>searches the method body represented by <code>cm</code> and -replaces all calls to <code>move()</code> in class <code>Point</code> -with a block: - -<ul><pre>{ $1 = 0; $_ = $proceed($$); } -</pre></ul> - -<p>so that the first parameter to <code>move()</code> is always 0. -Note that the substituted code is not an expression but -a statement or a block. It cannot be or contain a try-catch statement. - -<p>The method <code>instrument()</code> searches a method body. -If it finds an expression such as a method call, field access, and object -creation, then it calls <code>edit()</code> on the given -<code>ExprEditor</code> object. The parameter to <code>edit()</code> -is an object representing the found expression. The <code>edit()</code> -method can inspect and replace the expression through that object. - -<p>Calling <code>replace()</code> on the parameter to <code>edit()</code> -substitutes the given statement or block for the expression. If the given -block is an empty block, that is, if <code>replace("{}")</code> -is executed, then the expression is removed from the method body. - -If you want to insert a statement (or a block) before/after the -expression, a block like the following should be passed to -<code>replace()</code>: - -<ul><pre> -{ <em>before-statements;</em> - $_ = $proceed($$); - <em>after-statements;</em> } -</pre></ul> - -<p>whichever the expression is either a method call, field access, -object creation, or others. The second statement could be: - -<ul><pre>$_ = $proceed();</pre></ul> - -<p>if the expression is read access, or - -<ul><pre>$proceed($$);</pre></ul> - -<p>if the expression is write access. - -<p>Local variables available in the target expression is -also available in the source text passed to <code>replace()</code> -if the method searched by <code>instrument()</code> was compiled -with the -g option (the class file includes a local variable -attribute). - -<h4>javassist.expr.MethodCall</h4> - -<p>A <code>MethodCall</code> object represents a method call. -The method <code>replace()</code> in -<code>MethodCall</code> substitutes a statement or -a block for the method call. -It receives source text representing the substitued statement or -block, in which the identifiers starting with <code>$</code> -have special meaning as in the source text passed to -<code>insertBefore()</code>. - -<ul><table border=0> -<tr> -<td><code>$0</code></td> -<td rowspan=3> -The target object of the method call.<br> -This is not equivalent to <code>this</code>, which represents -the caller-side <code>this</code> object.<br> -<code>$0</code> is <code>null</code> if the method is static. -</td> -</tr> - -<tr><td> </td></tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$1</code>, <code>$2</code>, ...    </td> -<td> -The parameters of the method call. -</td> -</tr> - -<tr><td> -<code>$_</code></td> -<td>The resulting value of the method call.</td> -</tr> - -<tr><td><code>$r</code></td> -<td>The result type of the method call.</td> -</tr> - -<tr><td><code>$class</code>    </td> -<td>A <code>java.lang.Class</code> object representing -the class declaring the method. -</td> -</tr> - -<tr><td><code>$sig</code>    </td> -<td>An array of <code>java.lang.Class</code> objects representing -the formal parameter types.</td> -</tr> - -<tr><td><code>$type</code>    </td> -<td>A <code>java.lang.Class</code> object representing -the formal result type.</td> -</tr> - -<tr><td><code>$proceed</code>    </td> -<td>The name of the method originally called -in the expression.</td> -</tr> - -</table> -</ul> - -<p>Here the method call means the one represented by the -<code>MethodCall</code> object. - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<p>Unless the result type of the method call is <code>void</code>, -a value must be assigned to -<code>$_</code> in the source text and the type of <code>$_</code> -is the result type. -If the result type is <code>void</code>, the type of <code>$_</code> -is <code>Object</code> and the value assigned to <code>$_</code> -is ignored. - -<p><code>$proceed</code> is not a <code>String</code> value but special -syntax. It must be followed by an argument list surrounded by parentheses -<code>( )</code>. - -<h4>javassist.expr.ConstructorCall</h4> - -<p>A <code>ConstructorCall</code> object represents a constructor call -such as <code>this()</code> and <code>super</code> included in a constructor -body. -The method <code>replace()</code> in -<code>ConstructorCall</code> substitutes a statement or -a block for the constructor call. -It receives source text representing the substituted statement or -block, in which the identifiers starting with <code>$</code> -have special meaning as in the source text passed to -<code>insertBefore()</code>. - -<ul><table border=0> -<tr> -<td><code>$0</code></td> -<td> -The target object of the constructor call. -This is equivalent to <code>this</code>. -</td> -</tr> - -<tr> -<td><code>$1</code>, <code>$2</code>, ...    </td> -<td> -The parameters of the constructor call. -</td> -</tr> - -<tr><td><code>$class</code>    </td> -<td>A <code>java.lang.Class</code> object representing -the class declaring the constructor. -</td> -</tr> - -<tr><td><code>$sig</code>    </td> -<td>An array of <code>java.lang.Class</code> objects representing -the formal parameter types.</td> -</tr> - -<tr><td><code>$proceed</code>    </td> -<td>The name of the constructor originally called -in the expression.</td> -</tr> - -</table> -</ul> - -<p>Here the constructor call means the one represented by the -<code>ConstructorCall</code> object. - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<p>Since any constructor must call either a constructor of the super -class or another constructor of the same class, -the substituted statement must include a constructor call, -normally a call to <code>$proceed()</code>. - -<p><code>$proceed</code> is not a <code>String</code> value but special -syntax. It must be followed by an argument list surrounded by parentheses -<code>( )</code>. - -<h4>javassist.expr.FieldAccess</h4> - -<p>A <code>FieldAccess</code> object represents field access. -The method <code>edit()</code> in <code>ExprEditor</code> -receives this object if field access is found. -The method <code>replace()</code> in -<code>FieldAccess</code> receives -source text representing the substitued statement or -block for the field access. - -<p> -In the source text, the identifiers starting with <code>$</code> -have special meaning: - -<ul><table border=0> -<tr> -<td><code>$0</code></td> -<td rowspan=3> -The object containing the field accessed by the expression. -This is not equivalent to <code>this</code>.<br> -<code>this</code> represents the object that the method including the -expression is invoked on.<br> -<code>$0</code> is <code>null</code> if the field is static. -</td> -</tr> - -<tr><td> </td></tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$1</code></td> -<td rowspan=2> -The value that would be stored in the field -if the expression is write access. -<br>Otherwise, <code>$1</code> is not available. -</td> -</tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$_</code></td> -<td rowspan=2> -The resulting value of the field access -if the expression is read access. -<br>Otherwise, the value stored in <code>$_</code> is discarded. -</td> -</tr> - -<tr><td> </td></tr> -<tr> -<td><code>$r</code></td> -<td rowspan=2> -The type of the field if the expression is read access. -<br>Otherwise, <code>$r</code> is <code>void</code>. -</td> -</tr> - -<tr><td> </td></tr> - -<tr><td><code>$class</code>    </td> -<td>A <code>java.lang.Class</code> object representing -the class declaring the field. -</td></tr> - -<tr><td><code>$type</code></td> -<td>A <code>java.lang.Class</code> object representing -the field type.</td> -</tr> - -<tr><td><code>$proceed</code>    </td> -<td>The name of a virtual method executing the original -field access. -.</td> -</tr> - -</table> -</ul> - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<p>If the expression is read access, a value must be assigned to -<code>$_</code> in the source text. The type of <code>$_</code> -is the type of the field. - -<h4>javassist.expr.NewExpr</h4> - -<p>A <code>NewExpr</code> object represents object creation -with the <code>new</code> operator (not including array creation). -The method <code>edit()</code> in <code>ExprEditor</code> -receives this object if object creation is found. -The method <code>replace()</code> in -<code>NewExpr</code> receives -source text representing the substitued statement or -block for the object creation. - -<p> -In the source text, the identifiers starting with <code>$</code> -have special meaning: - -<ul><table border=0> - -<tr> -<td><code>$0</code></td> -<td> -<code>null</code>. -</td> -</tr> - -<tr> -<td><code>$1</code>, <code>$2</code>, ...    </td> -<td> -The parameters to the constructor. -</td> -</tr> - -<tr> -<td><code>$_</code></td> -<td rowspan=2> -The resulting value of the object creation. -<br>A newly created object must be stored in this variable. -</td> -</tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$r</code></td> -<td> -The type of the created object. -</td> -</tr> - -<tr><td><code>$sig</code>    </td> -<td>An array of <code>java.lang.Class</code> objects representing -the formal parameter types.</td> -</tr> - -<tr><td><code>$type</code>    </td> -<td>A <code>java.lang.Class</code> object representing -the class of the created object. -</td></tr> - -<tr><td><code>$proceed</code>    </td> -<td>The name of a virtual method executing the original -object creation. -.</td> -</tr> - -</table> -</ul> - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<h4>javassist.expr.NewArray</h4> - -<p>A <code>NewArray</code> object represents array creation -with the <code>new</code> operator. -The method <code>edit()</code> in <code>ExprEditor</code> -receives this object if array creation is found. -The method <code>replace()</code> in -<code>NewArray</code> receives -source text representing the substitued statement or -block for the array creation. - -<p> -In the source text, the identifiers starting with <code>$</code> -have special meaning: - -<ul><table border=0> - -<tr> -<td><code>$0</code></td> -<td> -<code>null</code>. -</td> -</tr> - -<tr> -<td><code>$1</code>, <code>$2</code>, ...    </td> -<td> -The size of each dimension. -</td> -</tr> - -<tr> -<td><code>$_</code></td> -<td rowspan=2> -The resulting value of the array creation. -<br>A newly created array must be stored in this variable. -</td> -</tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$r</code></td> -<td> -The type of the created array. -</td> -</tr> - -<tr><td><code>$type</code>    </td> -<td>A <code>java.lang.Class</code> object representing -the class of the created array. -</td></tr> - -<tr><td><code>$proceed</code>    </td> -<td>The name of a virtual method executing the original -array creation. -.</td> -</tr> - -</table> -</ul> - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<p>For example, if the array creation is the following expression, - -<ul><pre> -String[][] s = new String[3][4]; -</pre></ul> - -then the value of $1 and $2 are 3 and 4, respectively. $3 is not available. - -<p>If the array creation is the following expression, - -<ul><pre> -String[][] s = new String[3][]; -</pre></ul> - -then the value of $1 is 3 but $2 is not available. - -<h4>javassist.expr.Instanceof</h4> - -<p>A <code>Instanceof</code> object represents an <code>instanceof</code> -expression. -The method <code>edit()</code> in <code>ExprEditor</code> -receives this object if an instanceof expression is found. -The method <code>replace()</code> in -<code>Instanceof</code> receives -source text representing the substitued statement or -block for the expression. - -<p> -In the source text, the identifiers starting with <code>$</code> -have special meaning: - -<ul><table border=0> - -<tr> -<td><code>$0</code></td> -<td> -<code>null</code>. -</td> -</tr> - -<tr> -<td><code>$1</code></td> -<td> -The value on the left hand side of the original -<code>instanceof</code> operator. -</td> -</tr> - -<tr> -<td><code>$_</code></td> -<td> -The resulting value of the expression. -The type of <code>$_</code> is <code>boolean</code>. -</td> -</tr> - -<tr> -<td><code>$r</code></td> -<td> -The type on the right hand side of the <code>instanceof</code> operator. -</td> -</tr> - -<tr><td><code>$type</code></td> -<td>A <code>java.lang.Class</code> object representing -the type on the right hand side of the <code>instanceof</code> operator. -</td> -</tr> - -<tr><td><code>$proceed</code>    </td> -<td rowspan=4>The name of a virtual method executing the original -<code>instanceof</code> expression. -<br>It takes one parameter (the type is <code>java.lang.Object</code>) -and returns true -<br>if the parameter value is an instance of the type on the right -hand side of -<br>the original <code>instanceof</code> operator. -Otherwise, it returns false. -</td> -</tr> - -<tr><td> </td></tr> -<tr><td> </td></tr> -<tr><td> </td></tr> - -</table> -</ul> - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<h4>javassist.expr.Cast</h4> - -<p>A <code>Cast</code> object represents an expression for -explicit type casting. -The method <code>edit()</code> in <code>ExprEditor</code> -receives this object if explicit type casting is found. -The method <code>replace()</code> in -<code>Cast</code> receives -source text representing the substitued statement or -block for the expression. - -<p> -In the source text, the identifiers starting with <code>$</code> -have special meaning: - -<ul><table border=0> - -<tr> -<td><code>$0</code></td> -<td> -<code>null</code>. -</td> -</tr> - -<tr> -<td><code>$1</code></td> -<td> -The value the type of which is explicitly cast. -</td> -</tr> - -<tr> -<td><code>$_</code></td> -<td rowspan=2> -The resulting value of the expression. -The type of <code>$_</code> is the same as the type -<br>after the explicit casting, that is, the type surrounded -by <code>( )</code>. -</td> -</tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$r</code></td> -<td>the type after the explicit casting, or the type surrounded -by <code>( )</code>. -</td> -</tr> - -<tr><td><code>$type</code></td> -<td>A <code>java.lang.Class</code> object representing -the same type as <code>$r</code>. -</td> -</tr> - -<tr><td><code>$proceed</code>    </td> -<td rowspan=3>The name of a virtual method executing the original -type casting. -<br>It takes one parameter of the type <code>java.lang.Object</code> -and returns it after -<br>the explicit type casting specified by the original expression. - -</td> -</tr> - -<tr><td> </td></tr> - -<tr><td> </td></tr> - -</table> -</ul> - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<h4>javassist.expr.Handler</h4> - -<p>A <code>Handler</code> object represents a <code>catch</code> -clause of <code>try-catch</code> statement. -The method <code>edit()</code> in <code>ExprEditor</code> -receives this object if a <code>catch</code> is found. -The method <code>insertBefore()</code> in -<code>Handler</code> compiles the received -source text and inserts it at the beginning of the <code>catch</code> clause. - -<p> -In the source text, the identifiers starting with <code>$</code> -have meaning: - -<ul><table border=0> - -<tr> -<td><code>$1</code></td> -<td> -The exception object caught by the <code>catch</code> clause. -</td> -</tr> - -<tr> -<td><code>$r</code></td> -<td>the type of the exception caught by the <code>catch</code> clause. -It is used in a cast expression. -</td> -</tr> - -<tr> -<td><code>$w</code></td> -<td>The wrapper type. It is used in a cast expression. -</td> -</tr> - -<tr><td><code>$type</code>    </td> -<td rowspan=2> -A <code>java.lang.Class</code> object representing -<br>the type of the exception caught by the <code>catch</code> clause. -</td> -</tr> - -<tr><td> </td></tr> - -</table> -</ul> - -<p>If a new exception object is assigned to <code>$1</code>, -it is passed to the original <code>catch</code> clause as the caught -exception. - -<p><br> - -<a name="add"> -<h3>4.3 Adding a new method or field</h3> - -<h4>Adding a method</h4> - -<p>Javassist allows the users to create a new method and constructor -from scratch. <code>CtNewMethod</code> -and <code>CtNewConstructor</code> provide several factory methods, -which are static methods for creating <code>CtMethod</code> or -<code>CtConstructor</code> objects. -Especially, <code>make()</code> creates -a <code>CtMethod</code> or <code>CtConstructor</code> object -from the given source text. - -<p>For example, this program: - -<ul><pre> -CtClass point = ClassPool.getDefault().get("Point"); -CtMethod m = CtNewMethod.make( - "public int xmove(int dx) { x += dx; }", - point); -point.addMethod(m); -</pre></ul> - -<p>adds a public method <code>xmove()</code> to class <code>Point</code>. -In this example, <code>x</code> is a <code>int</code> field in -the class <code>Point</code>. - -<p>The source text passed to <code>make()</code> can include the -identifiers starting with <code>$</code> except <code>$_</code> -as in <code>setBody()</code>. -It can also include -<code>$proceed</code> if the target object and the target method name -are also given to <code>make()</code>. For example, - -<ul><pre> -CtClass point = ClassPool.getDefault().get("Point"); -CtMethod m = CtNewMethod.make( - "public int ymove(int dy) { $proceed(0, dy); }", - point, "this", "move"); -</pre></ul> - -<p>this program creates a method <code>ymove()</code> defined below: - -<ul><pre> -public int ymove(int dy) { this.move(0, dy); } -</pre></ul> - -<p>Note that <code>$proceed</code> has been replaced with -<code>this.move</code>. - -<p>Javassist provides another way to add a new method. -You can first create an abstract method and later give it a method body: - -<ul><pre> -CtClass cc = ... ; -CtMethod m = new CtMethod(CtClass.intType, "move", - new CtClass[] { CtClass.intType }, cc); -cc.addMethod(m); -m.setBody("{ x += $1; }"); -cc.setModifiers(cc.getModifiers() & ~Modifier.ABSTRACT); -</pre></ul> - -<p>Since Javassist makes a class abstract if an abstract method is -added to the class, you have to explicitly change the class back to a -non-abstract one after calling <code>setBody()</code>. - - -<h4>Mutual recursive methods</h4> - -<p>Javassist cannot compile a method if it calls another method that -has not been added to a class. (Javassist can compile a method that -calls itself recursively.) To add mutual recursive methods to a class, -you need a trick shown below. Suppose that you want to add methods -<code>m()</code> and <code>n()</code> to a class represented -by <code>cc</code>: - -<ul><pre> -CtClass cc = ... ; -CtMethod m = CtNewMethod.make("public abstract int m(int i);", cc); -CtMethod n = CtNewMethod.make("public abstract int n(int i);", cc); -cc.addMethod(m); -cc.addMethod(n); -m.setBody("{ return ($1 <= 0) ? 1 : (n($1 - 1) * $1); }"); -n.setBody("{ return m($1); }"); -cc.setModifiers(cc.getModifiers() & ~Modifier.ABSTRACT); -</pre></ul> - -<p>You must first make two abstract methods and add them to the class. -Then you can give the method bodies to these methods even if the method -bodies include method calls to each other. Finally you must change the -class to a not-abstract class since <code>addMethod()</code> automatically -changes a class into an abstract one if an abstract method is added. - -<h4>Adding a field</h4> - -<p>Javassist also allows the users to create a new field. - -<ul><pre> -CtClass point = ClassPool.getDefault().get("Point"); -CtField f = new CtField(CtClass.intType, "z", point); -point.addField(f); -</pre></ul> - -<p>This program adds a field named <code>z</code> to class -<code>Point</code>. - -<p>If the initial value of the added field must be specified, -the program shown above must be modified into: - -<ul><pre> -CtClass point = ClassPool.getDefault().get("Point"); -CtField f = new CtField(CtClass.intType, "z", point); -point.addField(f, "0"); <em>// initial value is 0.</em> -</pre></ul> - -<p>Now, the method <code>addField()</code> receives the second parameter, -which is the source text representing an expression computing the initial -value. This source text can be any Java expression if the result type -of the expression matches the type of the field. Note that an expression -does not end with a semi colon (<code>;</code>). - -<p>Furthermore, the above code can be rewritten into the following -simple code: - -<ul><pre> -CtClass point = ClassPool.getDefault().get("Point"); -CtField f = CtField.make("public int z = 0;", point); -point.addField(f); -</pre></ul> - -<h4>Removing a member</h4> - -<p>To remove a field or a method, call <code>removeField()</code> -or <code>removeMethod()</code> in <code>CtClass</code>. A -<code>CtConstructor</code> can be removed by <code>removeConstructor()</code> -in <code>CtClass</code>. - -<p><br> - -<a name="annotation"> -<h3>4.4 Annotations</h3> - -<p><code>CtClass</code>, <code>CtMethod</code>, <code>CtField</code> -and <code>CtConstructor</code> provides a convenient method -<code>getAnnotations()</code> for reading annotations. -It returns an annotation-type object. - -<p>For example, suppose the following annotation: - -<ul><pre> -public @interface Author { - String name(); - int year(); -} -</pre></ul> - -<p>This annotation is used as the following: - -<ul><pre> -@Author(name="Chiba", year=2005) -public class Point { - int x, y; -} -</pre></ul> - -<p>Then, the value of the annotation can be obtained by -<code>getAnnotations()</code>. -It returns an array containing -annotation-type objects. - -<ul><pre> -CtClass cc = ClassPool.getDefault().get("Point"); -Object[] all = cc.getAnnotations(); -Author a = (Author)all[0]; -String name = a.name(); -int year = a.year(); -System.out.println("name: " + name + ", year: " + year); -</pre></ul> - -<p>This code snippet should print: - -<ul><pre> -name: Chiba, year: 2005 -</pre></ul> - -<p> -Since the annoation of <code>Point</code> is only <code>@Author</code>, -the length of the array <code>all</code> is one -and <code>all[0]</code> is an <code>Author</code> object. -The member values of the annotation can be obtained -by calling <code>name()</code> and <code>year()</code> -on the <code>Author</code> object. - -<p>To use <code>getAnnotations()</code>, annotation types -such as <code>Author</code> must be included in the current -class path. <em>They must be also accessible from a -<code>ClassPool</code> object.</em> If the class file of an annotation -type is not found, Javassist cannot obtain the default values -of the members of that annotation type. - -<p><br> - -<a name="runtime"> -<h3>4.5 Runtime support classes</h3> - -<p>In most cases, a class modified by Javassist does not require -Javassist to run. However, some kinds of bytecode generated by the -Javassist compiler need runtime support classes, which are in the -<code>javassist.runtime</code> package (for details, please read -the API reference of that package). Note that the -<code>javassist.runtime</code> package is the only package that -classes modified by Javassist may need for running. The other -Javassist classes are never used at runtime of the modified classes. - -<p><br> - -<a name="import"> -<h3>4.6 Import</h3> - -<p>All the class names in source code must be fully qualified -(they must include package names). -However, the <code>java.lang</code> package is an -exception; for example, the Javassist compiler can -resolve <code>Object</code> as -well as <code>java.lang.Object</code>. - -<p>To tell the compiler to search other packages when resolving a -class name, call <code>importPackage()</code> in <code>ClassPool</code>. -For example, - -<ul><pre> -ClassPool pool = ClassPool.getDefault(); -pool.importPackage("java.awt"); -CtClass cc = pool.makeClass("Test"); -CtField f = CtField.make("public Point p;", cc); -cc.addField(f); -</pre></ul> - -<p>The seconde line instructs the compiler -to import the <code>java.awt</code> package. -Thus, the third line will not throw an exception. -The compiler can recognize <code>Point</code> -as <code>java.awt.Point</code>. - -<p>Note that <code>importPackage()</code> <em>does not</em> affect -the <code>get()</code> method in <code>ClassPool</code>. -Only the compiler considers the imported packages. -The parameter to <code>get()</code> -must be always a fully qualified name. - -<p><br> - -<a name="limit"> -<h3>4.7 Limitations</h3> - -<p>In the current implementation, the Java compiler included in Javassist -has several limitations with respect to the language that the compiler can -accept. Those limitations are: - -<p><li>The new syntax introduced by J2SE 5.0 (including enums and generics) -has not been supported. Annotations are supported by the low level -API of Javassist. -See the <code>javassist.bytecode.annotation</code> package -(and also <code>getAnnotations()</code> -in <code>CtClass</code> and <code>CtBehavior</code>). -Generics are also only partly supported. See <a href="./tutorial3.html#generics">the latter section</a> for more details. - -<p><li>Array initializers, a comma-separated list of expressions -enclosed by braces <code>{</code> and <code>}</code>, are not -available unless the array dimension is one. - -<p><li>Inner classes or anonymous classes are not supported. -Note that this is a limitation of the compiler only. -It cannot compile source code including an anonymous-class declaration. -Javassist can read and modify a class file of inner/anonymous class. - -<p><li>Labeled <code>continue</code> and <code>break</code> statements -are not supported. - -<p><li>The compiler does not correctly implement the Java method dispatch -algorithm. The compiler may confuse if methods defined in a class -have the same name but take different parameter lists. - -<p>For example, - -<ul><pre> -class A {} -class B extends A {} -class C extends B {} - -class X { - void foo(A a) { .. } - void foo(B b) { .. } -} -</pre></ul> - -<p>If the compiled expression is <code>x.foo(new C())</code>, where -<code>x</code> is an instance of X, the compiler may produce a call -to <code>foo(A)</code> although the compiler can correctly compile -<code>foo((B)new C())</code>. - -<p><li>The users are recommended to use <code>#</code> as the separator -between a class name and a static method or field name. -For example, in regular Java, - -<ul><pre>javassist.CtClass.intType.getName()</pre></ul> - -<p>calls a method <code>getName()</code> on -the object indicated by the static field <code>intType</code> -in <code>javassist.CtClass</code>. In Javassist, the users can -write the expression shown above but they are recommended to -write: - -<ul><pre>javassist.CtClass#intType.getName()</pre></ul> - -<p>so that the compiler can quickly parse the expression. -</ul> - -<p><br> - -<a href="tutorial.html">Previous page</a> - <a href="tutorial3.html">Next page</a> - -<hr> -Java(TM) is a trademark of Sun Microsystems, Inc.<br> -Copyright (C) 2000-2015 by Shigeru Chiba, All rights reserved. -</body> -</html> diff --git a/tutorial/tutorial3.html b/tutorial/tutorial3.html deleted file mode 100644 index cb2a6b3e..00000000 --- a/tutorial/tutorial3.html +++ /dev/null @@ -1,475 +0,0 @@ -<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> -<br><li><a href="#annotation">Annotations (Meta tags)</a> - -</ul> - -<p><a href="#generics">6. Generics</a> - -<p><a href="#varargs">7. Varargs</a> - -<p><a href="#j2me">8. J2ME</a> - -<p><a href="#boxing">9. Boxing/Unboxing - -<p><a href="#debug">10. Debug</a> - -<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. - -<p> -If you want to just produce a simple class file, -<code>javassist.bytecode.ClassFileWriter</code> might provide -the best API for you. It is much faster than -<code>javassist.bytecode.ClassFile</code> although its API -is minimum. - -<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>You can create a new class file from scratch. For example, -<blockquote><pre> -ClassFile cf = new ClassFile(false, "test.Foo", null); -cf.setInterfaces(new String[] { "java.lang.Cloneable" }); - -FieldInfo f = new FieldInfo(cf.getConstPool(), "width", "I"); -f.setAccessFlags(AccessFlag.PUBLIC); -cf.addField(f); - -cf.write(new DataOutputStream(new FileOutputStream("Foo.class"))); -</pre></blockquote> - -<p>this code generates a class file <code>Foo.class</code> that contains -the implementation of the following class: - -<blockquote><pre> -package test; -class Foo implements Cloneable { - public int width; -} -</pre></blockquote> - -<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 from a <code>ClassFile</code> object, -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>boolean hasNext()</code><br> -Returns true if there is more instructions.<br> -<li><code>int next()</code><br> -Returns the index of the next instruction.<br> -<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>The following code snippet displays all the instructions included -in a method body: - -<ul><pre> -CodeIterator ci = ... ; -while (ci.hasNext()) { - int index = ci.next(); - int op = ci.byteAt(index); - System.out.println(Mnemonic.OPCODE[op]); -} -</pre></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><code>Bytecode</code> can be used to construct a method. -For example, - -<blockquote><pre> -ClassFile cf = ... -Bytecode code = new Bytecode(cf.getConstPool()); -code.addAload(0); -code.addInvokespecial("java/lang/Object", MethodInfo.nameInit, "()V"); -code.addReturn(null); -code.setMaxLocals(1); - -MethodInfo minfo = new MethodInfo(cf.getConstPool(), MethodInfo.nameInit, "()V"); -minfo.setCodeAttribute(code.toCodeAttribute()); -cf.addMethod(minfo); -</pre></blockquote> - -<p>this code makes the default constructor and adds it to the class specified -by <code>cf</code>. The <code>Bytecode</code> object is first converted into -a <code>CodeAttribute</code> object and then added to the method specified -by <code>minfo</code>. The method is finally added to a class file <code>cf</code>. - -<p><br> - -<a name="annotation"> -<h3>5.5 Annotations (Meta tags)</h3> - -<p>Annotations are stored in a class file -as runtime invisible (or visible) annotations attribute. -These attributes can be obtained from <code>ClassFile</code>, -<code>MethodInfo</code>, or <code>FieldInfo</code> objects. -Call <code>getAttribute(AnnotationsAttribute.invisibleTag)</code> -on those objects. For more details, see the javadoc manual -of <code>javassist.bytecode.AnnotationsAttribute</code> class -and the <code>javassist.bytecode.annotation</code> package. - -<p>Javassist also let you access annotations by the higher-level -API. -If you want to access annotations through <code>CtClass</code>, -call <code>getAnnotations()</code> in <code>CtClass</code> or -<code>CtBehavior</code>. - -<p><br> - -<h2><a name="generics">6. Generics</a></h2> - -<p>The lower-level API of Javassist fully supports generics -introduced by Java 5. On the other hand, the higher-level -API such as <code>CtClass</code> does not directly support -generics. However, this is not a serious problem for bytecode -transformation. - -<p>The generics of Java is implemented by the erasure technique. -After compilation, all type parameters are dropped off. For -example, suppose that your source code declares a parameterized -type <code>Vector<String></code>: - -<ul><pre> -Vector<String> v = new Vector<String>(); - : -String s = v.get(0); -</pre></ul> - -<p>The compiled bytecode is equivalent to the following code: - -<ul><pre> -Vector v = new Vector(); - : -String s = (String)v.get(0); -</pre></ul> - -<p>So when you write a bytecode transformer, you can just drop -off all type parameters. Because the compiler embedded in Javassist -does not support generics, -you must insert an explicit type cast at the -caller site if the source code is compiled by Javassist, for example, -through <code>CtMethod.make()</code>. No type cast -is necessary if the source code is compiled by a normal Java compiler -such as <code>javac</code>. - -<p>For example, if you have a class: - -<ul><pre> -public class Wrapper<T> { - T value; - public Wrapper(T t) { value = t; } -} -</pre></ul> - -<p>and want to add an interface <code>Getter<T></code> to the -class <code>Wrapper<T></code>: - -<ul><pre> -public interface Getter<T> { - T get(); -} -</pre></ul> - -<p>then the interface you really have to add is <code>Getter</code> -(the type parameters <code><T></code> drops off) -and the method you also have to add to the <code>Wrapper</code> -class is this simple one: - -<ul><pre> -public Object get() { return value; } -</pre></ul> - -<p>Note that no type parameters are necessary. -Since <code>get</code> returns an <code>Object</code>, an explicit type cast -is needed at the caller site if the source code is compiled by Javassist. -For example, if the type parameter <code>T</code> -is <code>String</code>, then <code>(String)</code> must be inserted as follows: - -<ul><pre> -Wrapper w = ... -String s = (String)w.get(); -</pre></ul> - -<p>The type cast is not needed if the source code is compiled by a normal Java -compiler because it will automatically insert a type cast. - -<p>If you need to make type parameters accessible through reflection -during runtime, you have to add generic signatures to the class file. -For more details, see the API documentation (javadoc) of the -<code>setGenericSignature</code> method in the <code>CtClass</code>. - -<p><br> - -<h2><a name="varargs">7. Varargs</a></h2> - -<p>Currently, Javassist does not directly support varargs. So to make a method with varargs, -you must explicitly set a method modifier. But this is easy. -Suppose that now you want to make the following method: - -<ul><pre> -public int length(int... args) { return args.length; } -</pre></ul> - -<p>The following code using Javassist will make the method shown above: - -<ul><pre> -CtClass cc = /* target class */; -CtMethod m = CtMethod.make("public int length(int[] args) { return args.length; }", cc); -m.setModifiers(m.getModifiers() | Modifier.VARARGS); -cc.addMethod(m); -<pre></ul> - -<p>The parameter type <code>int...</code> is changed into <code>int[]</code> -and <code>Modifier.VARARGS</code> is added to the method modifiers. - -<p>To call this method in the source code compiled by the compiler embedded in Javassist, -you must write: - -<ul><pre> -length(new int[] { 1, 2, 3 }); -</pre></ul> - -<p>instead of this method call using the varargs mechanism: - -<ul><pre> -length(1, 2, 3); -</pre></ul> - -<p><br> - -<h2><a name="j2me">8. J2ME</a></h2> - -<p>If you modify a class file for the J2ME execution environment, -you must perform <it>preverification</it>. Preverifying is basically -producing stack maps, which is similar to stack map tables introduced -into J2SE at JDK 1.6. Javassist maintains the stack maps for J2ME only if -<code>javassist.bytecode.MethodInfo.doPreverify</code> is true. - -<p>You can also manually -produce a stack map for a modified method. -For a given method represented by a <code>CtMethod</code> object <code>m</code>, -you can produce a stack map by calling the following methods: - -<ul><pre> -m.getMethodInfo().rebuildStackMapForME(cpool); -</pre></ul> - -<p>Here, <code>cpool</code> is a <code>ClassPool</code> object, which is -available by calling <code>getClassPool()</code> on a <code>CtClass</code> -object. A <code>ClassPool</code> object is responsible for finding -class files from given class pathes. To obtain all the <code>CtMethod</code> -objects, call the <code>getDeclaredMethods</code> method on a <code>CtClass</code> object. - -<p><br> - -<h2><a name="boxing">9. Boxing/Unboxing</h2> - -<p>Boxing and unboxing in Java are syntactic sugar. There is no bytecode for -boxing or unboxing. So the compiler of Javassist does not support them. -For example, the following statement is valid in Java: - -<ul><pre> -Integer i = 3; -</pre></ul> - -<p>since boxing is implicitly performed. For Javassist, however, you must explicitly -convert a value type from <code>int</code> to <code>Integer</code>: - -<ul><pre> -Integer i = new Integer(3); -</pre></ul> - -<p><br> - -<h2><a name="debug">10. Debug</h2> - -<p>Set <code>CtClass.debugDump</code> to a directory name. -Then all class files modified and generated by Javassist are saved in that -directory. To stop this, set <code>CtClass.debugDump</code> to null. -The default value is null. - -<p>For example, - -<ul><pre> -CtClass.debugDump = "./dump"; -</pre></ul> - -<p>All modified class files are saved in <code>./dump</code>. - -<p><br> - -<a href="tutorial2.html">Previous page</a> - -<hr> -Java(TM) is a trademark of Sun Microsystems, Inc.<br> -Copyright (C) 2000-2015 by Shigeru Chiba, All rights reserved. -</body> -</html> |