<h1>Javassist version 3</h1> | <h1>Javassist version 3</h1> | ||||
<h3>Copyright (C) 1999-2013 by Shigeru Chiba, All rights reserved.</h3> | |||||
<h3>Copyright (C) 1999-2015 by Shigeru Chiba, All rights reserved.</h3> | |||||
<p><br></p> | <p><br></p> | ||||
<table> | <table> | ||||
<tr> | <tr> | ||||
<td><li><tt><a href="License.html">License.html</a></tt></td> | <td><li><tt><a href="License.html">License.html</a></tt></td> | ||||
<td>License file | |||||
<td>License file (MPL/LGPL/Apache triple license) | |||||
(Also see the <a href="#copyright">copyright notices</a> below)</td> | (Also see the <a href="#copyright">copyright notices</a> below)</td> | ||||
</tr> | </tr> | ||||
<h2>Changes</h2> | <h2>Changes</h2> | ||||
<p>-version 3.19 | |||||
<p>-version 3.19 on January 6, 2015 | |||||
<ul> | <ul> | ||||
<li>JIRA JASSIST-158, 205, 206, 207, 208, 209, 211, 212, 216, 220, 223, 224, | <li>JIRA JASSIST-158, 205, 206, 207, 208, 209, 211, 212, 216, 220, 223, 224, | ||||
227, 230, 234, 235, 236, 237, 238, 240. | 227, 230, 234, 235, 236, 237, 238, 240. |
<project name="javassist" default="jar" basedir="."> | <project name="javassist" default="jar" basedir="."> | ||||
<property name="dist-version" value="javassist-3.18.0-GA"/> | |||||
<property name="dist-version" value="javassist-3.19.0-GA"/> | |||||
<property environment="env"/> | <property environment="env"/> | ||||
<property name="target.jar" value="javassist.jar"/> | <property name="target.jar" value="javassist.jar"/> |
Javassist (JAVA programming ASSISTant) makes Java bytecode manipulation | Javassist (JAVA programming ASSISTant) makes Java bytecode manipulation | ||||
simple. It is a class library for editing bytecodes in Java. | simple. It is a class library for editing bytecodes in Java. | ||||
</description> | </description> | ||||
<version>3.18.0-GA</version> | |||||
<version>3.19.0-GA</version> | |||||
<name>Javassist</name> | <name>Javassist</name> | ||||
<url>http://www.javassist.org/</url> | <url>http://www.javassist.org/</url> | ||||
Specification-Title: Javassist | Specification-Title: Javassist | ||||
Specification-Vendor: Shigeru Chiba, www.javassist.org | Specification-Vendor: Shigeru Chiba, www.javassist.org | ||||
Specification-Version: 3.18.0-GA | |||||
Specification-Version: 3.19.0-GA | |||||
Main-Class: javassist.CtClass | Main-Class: javassist.CtClass |
* into a <code>CtClass</code> object representing the class with a name | * into a <code>CtClass</code> object representing the class with a name | ||||
* <code>classname</code>, then do as following: | * <code>classname</code>, then do as following: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* ClassPool cp = ClassPool.getDefault(); | * ClassPool cp = ClassPool.getDefault(); | ||||
* cp.insertClassPath(new ByteArrayClassPath(classname, b)); | * cp.insertClassPath(new ByteArrayClassPath(classname, b)); | ||||
* CtClass cc = cp.get(classname); | * CtClass cc = cp.get(classname); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>The <code>ClassPool</code> object <code>cp</code> uses the created | * <p>The <code>ClassPool</code> object <code>cp</code> uses the created | ||||
* <code>ByteArrayClassPath</code> object as the source of the class file. | * <code>ByteArrayClassPath</code> object as the source of the class file. |
* with a user-defined class loader and any class files are not found with | * with a user-defined class loader and any class files are not found with | ||||
* the default <code>ClassPool</code>. For example, | * the default <code>ClassPool</code>. For example, | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* ClassPool cp = ClassPool.getDefault(); | * ClassPool cp = ClassPool.getDefault(); | ||||
* cp.insertClassPath(new ClassClassPath(this.getClass())); | * cp.insertClassPath(new ClassClassPath(this.getClass())); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* This code snippet permanently adds a <code>ClassClassPath</code> | * This code snippet permanently adds a <code>ClassClassPath</code> | ||||
* to the default <code>ClassPool</code>. Note that the default | * to the default <code>ClassPool</code>. Note that the default |
* definition or a method body. Define a subclass of this class | * definition or a method body. Define a subclass of this class | ||||
* if a more complex mapping algorithm is needed. For example, | * if a more complex mapping algorithm is needed. For example, | ||||
* | * | ||||
* <ul><pre>class MyClassMap extends ClassMap { | |||||
* <pre>class MyClassMap extends ClassMap { | |||||
* public Object get(Object jvmClassName) { | * public Object get(Object jvmClassName) { | ||||
* String name = toJavaName((String)jvmClassName); | * String name = toJavaName((String)jvmClassName); | ||||
* if (name.startsWith("java.")) | * if (name.startsWith("java.")) | ||||
* else | * else | ||||
* return super.get(jvmClassName); | * return super.get(jvmClassName); | ||||
* } | * } | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>This subclass maps <code>java.lang.String</code> to | * <p>This subclass maps <code>java.lang.String</code> to | ||||
* <code>java2.lang.String</code>. Note that <code>get()</code> | * <code>java2.lang.String</code>. Note that <code>get()</code> |
* <p>When this method is called for the first time, the default | * <p>When this method is called for the first time, the default | ||||
* class pool is created with the following code snippet: | * class pool is created with the following code snippet: | ||||
* | * | ||||
* <ul><code>ClassPool cp = new ClassPool(); | |||||
* <pre>ClassPool cp = new ClassPool(); | |||||
* cp.appendSystemPath(); | * cp.appendSystemPath(); | ||||
* </code></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>If the default class pool cannot find any class files, | * <p>If the default class pool cannot find any class files, | ||||
* try <code>ClassClassPath</code> and <code>LoaderClassPath</code>. | * try <code>ClassClassPath</code> and <code>LoaderClassPath</code>. | ||||
* This method is useful if you want to generate a new class as a copy | * This method is useful if you want to generate a new class as a copy | ||||
* of another class (except the class name). For example, | * of another class (except the class name). For example, | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* getAndRename("Point", "Pair") | * getAndRename("Point", "Pair") | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* returns a <code>CtClass</code> object representing <code>Pair</code> | * returns a <code>CtClass</code> object representing <code>Pair</code> | ||||
* class. The definition of <code>Pair</code> is the same as that of | * class. The definition of <code>Pair</code> is the same as that of |
* <code>CtMethod.instrument()</code> as a parameter. | * <code>CtMethod.instrument()</code> as a parameter. | ||||
* | * | ||||
* <p>Example: | * <p>Example: | ||||
* <ul><pre> | |||||
* <pre> | |||||
* ClassPool cp = ClassPool.getDefault(); | * ClassPool cp = ClassPool.getDefault(); | ||||
* CtClass point = cp.get("Point"); | * CtClass point = cp.get("Point"); | ||||
* CtClass singleton = cp.get("Singleton"); | * CtClass singleton = cp.get("Singleton"); | ||||
* CodeConverter conv = new CodeConverter(); | * CodeConverter conv = new CodeConverter(); | ||||
* conv.replaceNew(point, singleton, "makePoint"); | * conv.replaceNew(point, singleton, "makePoint"); | ||||
* client.instrument(conv); | * client.instrument(conv); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>This program substitutes "<code>Singleton.makePoint()</code>" | * <p>This program substitutes "<code>Singleton.makePoint()</code>" | ||||
* for all occurrences of "<code>new Point()</code>" | * for all occurrences of "<code>new Point()</code>" | ||||
* <code>Singleton</code>, respectively) | * <code>Singleton</code>, respectively) | ||||
* replaces all occurrences of: | * replaces all occurrences of: | ||||
* | * | ||||
* <ul><code>new Point(x, y)</code></ul> | |||||
* <pre>new Point(x, y)</pre> | |||||
* | * | ||||
* in the method body with: | * in the method body with: | ||||
* | * | ||||
* <ul><code>Singleton.createPoint(x, y)</code></ul> | |||||
* <pre>Singleton.createPoint(x, y)</pre> | |||||
* | * | ||||
* <p>This enables to intercept instantiation of <code>Point</code> | * <p>This enables to intercept instantiation of <code>Point</code> | ||||
* and change the samentics. For example, the following | * and change the samentics. For example, the following | ||||
* <code>createPoint()</code> implements the singleton pattern: | * <code>createPoint()</code> implements the singleton pattern: | ||||
* | * | ||||
* <ul><pre>public static Point createPoint(int x, int y) { | |||||
* <pre>public static Point createPoint(int x, int y) { | |||||
* if (aPoint == null) | * if (aPoint == null) | ||||
* aPoint = new Point(x, y); | * aPoint = new Point(x, y); | ||||
* return aPoint; | * return aPoint; | ||||
* } | * } | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>The static method call substituted for the original <code>new</code> | * <p>The static method call substituted for the original <code>new</code> | ||||
* expression must be | * expression must be | ||||
* <code>Point2</code>, respectively) | * <code>Point2</code>, respectively) | ||||
* replaces all occurrences of: | * replaces all occurrences of: | ||||
* | * | ||||
* <ul><code>new Point(x, y)</code></ul> | |||||
* <pre>new Point(x, y)</pre> | |||||
* | * | ||||
* in the method body with: | * in the method body with: | ||||
* | * | ||||
* <ul><code>new Point2(x, y)</code></ul> | |||||
* <pre>new Point2(x, y)</pre> | |||||
* | * | ||||
* <p>Note that <code>Point2</code> must be type-compatible with <code>Point</code>. | * <p>Note that <code>Point2</code> must be type-compatible with <code>Point</code>. | ||||
* It must have the same set of methods, fields, and constructors as the | * It must have the same set of methods, fields, and constructors as the | ||||
* | * | ||||
* <p>For example, the program below | * <p>For example, the program below | ||||
* | * | ||||
* <ul><pre>Point p = new Point(); | |||||
* int newX = p.x + 3;</pre></ul> | |||||
* <pre>Point p = new Point(); | |||||
* int newX = p.x + 3;</pre> | |||||
* | * | ||||
* <p>can be translated into: | * <p>can be translated into: | ||||
* | * | ||||
* <ul><pre>Point p = new Point(); | |||||
* int newX = Accessor.readX(p) + 3;</pre></ul> | |||||
* <pre>Point p = new Point(); | |||||
* int newX = Accessor.readX(p) + 3;</pre> | |||||
* | * | ||||
* <p>where | * <p>where | ||||
* | * | ||||
* <ul><pre>public class Accessor { | |||||
* <pre>public class Accessor { | |||||
* public static int readX(Object target) { ... } | * public static int readX(Object target) { ... } | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>The type of the parameter of <code>readX()</code> must | * <p>The type of the parameter of <code>readX()</code> must | ||||
* be <code>java.lang.Object</code> independently of the actual | * be <code>java.lang.Object</code> independently of the actual | ||||
* | * | ||||
* <p>For example, the program below | * <p>For example, the program below | ||||
* | * | ||||
* <ul><pre>Point p = new Point(); | |||||
* p.x = 3;</pre></ul> | |||||
* <pre>Point p = new Point(); | |||||
* p.x = 3;</pre> | |||||
* | * | ||||
* <p>can be translated into: | * <p>can be translated into: | ||||
* | * | ||||
* <ul><pre>Point p = new Point(); | |||||
* Accessor.writeX(3);</pre></ul> | |||||
* <pre>Point p = new Point(); | |||||
* Accessor.writeX(3);</pre> | |||||
* | * | ||||
* <p>where | * <p>where | ||||
* | * | ||||
* <ul><pre>public class Accessor { | |||||
* <pre>public class Accessor { | |||||
* public static void writeX(Object target, int value) { ... } | * public static void writeX(Object target, int value) { ... } | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>The type of the first parameter of <code>writeX()</code> must | * <p>The type of the first parameter of <code>writeX()</code> must | ||||
* be <code>java.lang.Object</code> independently of the actual | * be <code>java.lang.Object</code> independently of the actual | ||||
* method. For example, if the originally invoked method is | * method. For example, if the originally invoked method is | ||||
* <code>move()</code>: | * <code>move()</code>: | ||||
* | * | ||||
* <ul><pre>class Point { | |||||
* <pre>class Point { | |||||
* Point move(int x, int y) { ... } | * Point move(int x, int y) { ... } | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>Then the before method must be something like this: | * <p>Then the before method must be something like this: | ||||
* | * | ||||
* <ul><pre>class Verbose { | |||||
* <pre>class Verbose { | |||||
* static void print(Point target, int x, int y) { ... } | * static void print(Point target, int x, int y) { ... } | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>The <code>CodeConverter</code> would translate bytecode | * <p>The <code>CodeConverter</code> would translate bytecode | ||||
* equivalent to: | * equivalent to: | ||||
* | * | ||||
* <ul><pre>Point p2 = p.move(x + y, 0);</pre></ul> | |||||
* <pre>Point p2 = p.move(x + y, 0);</pre> | |||||
* | * | ||||
* <p>into the bytecode equivalent to: | * <p>into the bytecode equivalent to: | ||||
* | * | ||||
* <ul><pre>int tmp1 = x + y; | |||||
* <pre>int tmp1 = x + y; | |||||
* int tmp2 = 0; | * int tmp2 = 0; | ||||
* Verbose.print(p, tmp1, tmp2); | * Verbose.print(p, tmp1, tmp2); | ||||
* Point p2 = p.move(tmp1, tmp2);</pre></ul> | |||||
* Point p2 = p.move(tmp1, tmp2);</pre> | |||||
* | * | ||||
* @param origMethod the method originally invoked. | * @param origMethod the method originally invoked. | ||||
* @param beforeMethod the method invoked before | * @param beforeMethod the method invoked before | ||||
* method. For example, if the originally invoked method is | * method. For example, if the originally invoked method is | ||||
* <code>move()</code>: | * <code>move()</code>: | ||||
* | * | ||||
* <ul><pre>class Point { | |||||
* <pre>class Point { | |||||
* Point move(int x, int y) { ... } | * Point move(int x, int y) { ... } | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>Then the after method must be something like this: | * <p>Then the after method must be something like this: | ||||
* | * | ||||
* <ul><pre>class Verbose { | |||||
* <pre>class Verbose { | |||||
* static void print(Point target, int x, int y) { ... } | * static void print(Point target, int x, int y) { ... } | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>The <code>CodeConverter</code> would translate bytecode | * <p>The <code>CodeConverter</code> would translate bytecode | ||||
* equivalent to: | * equivalent to: | ||||
* | * | ||||
* <ul><pre>Point p2 = p.move(x + y, 0);</pre></ul> | |||||
* <pre>Point p2 = p.move(x + y, 0);</pre> | |||||
* | * | ||||
* <p>into the bytecode equivalent to: | * <p>into the bytecode equivalent to: | ||||
* | * | ||||
* <ul><pre>int tmp1 = x + y; | |||||
* <pre> | |||||
* int tmp1 = x + y; | |||||
* int tmp2 = 0; | * int tmp2 = 0; | ||||
* Point p2 = p.move(tmp1, tmp2); | * Point p2 = p.move(tmp1, tmp2); | ||||
* Verbose.print(p, tmp1, tmp2);</pre></ul> | |||||
* Verbose.print(p, tmp1, tmp2);</pre> | |||||
* | * | ||||
* @param origMethod the method originally invoked. | * @param origMethod the method originally invoked. | ||||
* @param afterMethod the method invoked after | * @param afterMethod the method invoked after |
/** | /** | ||||
* The version number of this release. | * The version number of this release. | ||||
*/ | */ | ||||
public static final String version = "3.18.0-GA"; | |||||
public static final String version = "3.19.0-GA"; | |||||
/** | /** | ||||
* Prints the version number and the copyright notice. | * Prints the version number and the copyright notice. | ||||
* | * | ||||
* <p>The following command invokes this method: | * <p>The following command invokes this method: | ||||
* | * | ||||
* <ul><pre>java -jar javassist.jar</pre></ul> | |||||
* <pre>java -jar javassist.jar</pre> | |||||
*/ | */ | ||||
public static void main(String[] args) { | public static void main(String[] args) { | ||||
System.out.println("Javassist version " + CtClass.version); | System.out.println("Javassist version " + CtClass.version); | ||||
System.out.println("Copyright (C) 1999-2013 Shigeru Chiba." | |||||
System.out.println("Copyright (C) 1999-2015 Shigeru Chiba." | |||||
+ " All Rights Reserved."); | + " All Rights Reserved."); | ||||
} | } | ||||
* | * | ||||
* <p>For example, | * <p>For example, | ||||
* | * | ||||
* <pre>class List<T> { | |||||
* <pre>class List<T> { | |||||
* T value; | * T value; | ||||
* T get() { return value; } | * T get() { return value; } | ||||
* void set(T v) { value = v; } | * void set(T v) { value = v; } | ||||
* Any regular Java expression can be used for specifying the initial | * Any regular Java expression can be used for specifying the initial | ||||
* value. The followings are examples. | * value. The followings are examples. | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* cc.addField(f, "0") // the initial value is 0. | * cc.addField(f, "0") // the initial value is 0. | ||||
* cc.addField(f, "i + 1") // i + 1. | * cc.addField(f, "i + 1") // i + 1. | ||||
* cc.addField(f, "new Point()"); // a Point object. | * cc.addField(f, "new Point()"); // a Point object. | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>Here, the type of variable <code>cc</code> is <code>CtClass</code>. | * <p>Here, the type of variable <code>cc</code> is <code>CtClass</code>. | ||||
* The type of <code>f</code> is <code>CtField</code>. | * The type of <code>f</code> is <code>CtField</code>. | ||||
* | * | ||||
* <p>For example, | * <p>For example, | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* CtClass cc = ...; | * CtClass cc = ...; | ||||
* addField(new CtField(CtClass.intType, "i", cc), | * addField(new CtField(CtClass.intType, "i", cc), | ||||
* CtField.Initializer.constant(1)); | * CtField.Initializer.constant(1)); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>This code adds an <code>int</code> field named "i". The | * <p>This code adds an <code>int</code> field named "i". The | ||||
* initial value of this field is 1. | * initial value of this field is 1. | ||||
* <code>javassist.bytecode</code> package. For example, the following | * <code>javassist.bytecode</code> package. For example, the following | ||||
* expression returns all the attributes of a class file. | * expression returns all the attributes of a class file. | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* getClassFile().getAttributes() | * getClassFile().getAttributes() | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* @param name attribute name | * @param name attribute name | ||||
* @see javassist.bytecode.AttributeInfo | * @see javassist.bytecode.AttributeInfo | ||||
* <code>javassist.bytecode</code> package. For example, the following | * <code>javassist.bytecode</code> package. For example, the following | ||||
* expression adds an attribute <code>info</code> to a class file. | * expression adds an attribute <code>info</code> to a class file. | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* getClassFile().addAttribute(info) | * getClassFile().addAttribute(info) | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* @param name attribute name | * @param name attribute name | ||||
* @param data attribute value | * @param data attribute value |
* Compiles the given source code and creates a field. | * Compiles the given source code and creates a field. | ||||
* Examples of the source code are: | * Examples of the source code are: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* "public String name;" | * "public String name;" | ||||
* "public int k = 3;"</pre></ul> | |||||
* "public int k = 3;"</pre> | |||||
* | * | ||||
* <p>Note that the source code ends with <code>';'</code> | * <p>Note that the source code ends with <code>';'</code> | ||||
* (semicolon). | * (semicolon). | ||||
* value of the field. The constructor of the created object receives | * value of the field. The constructor of the created object receives | ||||
* the parameter: | * the parameter: | ||||
* | * | ||||
* <ul><code>Object obj</code> - the object including the field.<br> | |||||
* </ul> | |||||
* <p><code>Object obj</code> - the object including the field. | |||||
* | * | ||||
* <p>If the initialized field is static, then the constructor does | * <p>If the initialized field is static, then the constructor does | ||||
* not receive any parameters. | * not receive any parameters. | ||||
* value of the field. The constructor of the created object receives | * value of the field. The constructor of the created object receives | ||||
* the parameters: | * the parameters: | ||||
* | * | ||||
* <ul><code>Object obj</code> - the object including the field.<br> | |||||
* <p><code>Object obj</code> - the object including the field.<br> | |||||
* <code>String[] strs</code> - the character strings specified | * <code>String[] strs</code> - the character strings specified | ||||
* by <code>stringParams</code><br> | * by <code>stringParams</code><br> | ||||
* </ul> | |||||
* | * | ||||
* <p>If the initialized field is static, then the constructor | * <p>If the initialized field is static, then the constructor | ||||
* receives only <code>strs</code>. | * receives only <code>strs</code>. | ||||
* value of the field. The constructor of the created object receives | * value of the field. The constructor of the created object receives | ||||
* the parameters: | * the parameters: | ||||
* | * | ||||
* <ul><code>Object obj</code> - the object including the field.<br> | |||||
* <p><code>Object obj</code> - the object including the field.<br> | |||||
* <code>Object[] args</code> - the parameters passed to the | * <code>Object[] args</code> - the parameters passed to the | ||||
* constructor of the object including the | * constructor of the object including the | ||||
* filed. | * filed. | ||||
* </ul> | |||||
* | * | ||||
* <p>If the initialized field is static, then the constructor does | * <p>If the initialized field is static, then the constructor does | ||||
* not receive any parameters. | * not receive any parameters. | ||||
* value of the field. The constructor of the created object receives | * value of the field. The constructor of the created object receives | ||||
* the parameters: | * the parameters: | ||||
* | * | ||||
* <ul><code>Object obj</code> - the object including the field.<br> | |||||
* <p><code>Object obj</code> - the object including the field.<br> | |||||
* <code>String[] strs</code> - the character strings specified | * <code>String[] strs</code> - the character strings specified | ||||
* by <code>stringParams</code><br> | * by <code>stringParams</code><br> | ||||
* <code>Object[] args</code> - the parameters passed to the | * <code>Object[] args</code> - the parameters passed to the | ||||
* constructor of the object including the | * constructor of the object including the | ||||
* filed. | * filed. | ||||
* </ul> | |||||
* | * | ||||
* <p>If the initialized field is static, then the constructor receives | * <p>If the initialized field is static, then the constructor receives | ||||
* only <code>strs</code>. | * only <code>strs</code>. | ||||
* value as the initial value of the field. | * value as the initial value of the field. | ||||
* The called method receives the parameters: | * The called method receives the parameters: | ||||
* | * | ||||
* <ul><code>Object obj</code> - the object including the field.<br> | |||||
* </ul> | |||||
* <p><code>Object obj</code> - the object including the field. | |||||
* | * | ||||
* <p>If the initialized field is static, then the method does | * <p>If the initialized field is static, then the method does | ||||
* not receive any parameters. | * not receive any parameters. | ||||
* value as the initial value of the field. The called method | * value as the initial value of the field. The called method | ||||
* receives the parameters: | * receives the parameters: | ||||
* | * | ||||
* <ul><code>Object obj</code> - the object including the field.<br> | |||||
* <p><code>Object obj</code> - the object including the field.<br> | |||||
* <code>String[] strs</code> - the character strings specified | * <code>String[] strs</code> - the character strings specified | ||||
* by <code>stringParams</code><br> | * by <code>stringParams</code><br> | ||||
* </ul> | |||||
* | * | ||||
* <p>If the initialized field is static, then the method | * <p>If the initialized field is static, then the method | ||||
* receive only <code>strs</code>. | * receive only <code>strs</code>. | ||||
* value as the initial value of the field. The called method | * value as the initial value of the field. The called method | ||||
* receives the parameters: | * receives the parameters: | ||||
* | * | ||||
* <ul><code>Object obj</code> - the object including the field.<br> | |||||
* <p><code>Object obj</code> - the object including the field.<br> | |||||
* <code>Object[] args</code> - the parameters passed to the | * <code>Object[] args</code> - the parameters passed to the | ||||
* constructor of the object including the | * constructor of the object including the | ||||
* filed. | * filed. | ||||
* </ul> | |||||
* | * | ||||
* <p>If the initialized field is static, then the method does | * <p>If the initialized field is static, then the method does | ||||
* not receive any parameters. | * not receive any parameters. | ||||
* value as the initial value of the field. The called method | * value as the initial value of the field. The called method | ||||
* receives the parameters: | * receives the parameters: | ||||
* | * | ||||
* <ul><code>Object obj</code> - the object including the field.<br> | |||||
* <p><code>Object obj</code> - the object including the field.<br> | |||||
* <code>String[] strs</code> - the character strings specified | * <code>String[] strs</code> - the character strings specified | ||||
* by <code>stringParams</code><br> | * by <code>stringParams</code><br> | ||||
* <code>Object[] args</code> - the parameters passed to the | * <code>Object[] args</code> - the parameters passed to the | ||||
* constructor of the object including the | * constructor of the object including the | ||||
* filed. | * filed. | ||||
* </ul> | |||||
* | * | ||||
* <p>If the initialized field is static, then the method | * <p>If the initialized field is static, then the method | ||||
* receive only <code>strs</code>. | * receive only <code>strs</code>. |
* <p>For example, suppose that a method <code>at()</code> is as | * <p>For example, suppose that a method <code>at()</code> is as | ||||
* follows: | * follows: | ||||
* | * | ||||
* <ul><pre>public X at(int i) { | |||||
* <pre> | |||||
* public X at(int i) { | |||||
* return (X)super.elementAt(i); | * return (X)super.elementAt(i); | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>(<code>X</code> is a class name.) If <code>map</code> substitutes | * <p>(<code>X</code> is a class name.) If <code>map</code> substitutes | ||||
* <code>String</code> for <code>X</code>, then the created method is: | * <code>String</code> for <code>X</code>, then the created method is: | ||||
* | * | ||||
* <ul><pre>public String at(int i) { | |||||
* <pre> | |||||
* public String at(int i) { | |||||
* return (String)super.elementAt(i); | * return (String)super.elementAt(i); | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>By default, all the occurrences of the names of the class | * <p>By default, all the occurrences of the names of the class | ||||
* declaring <code>at()</code> and the superclass are replaced | * declaring <code>at()</code> and the superclass are replaced |
* <code>Object</code>. The signature of the super's constructor | * <code>Object</code>. The signature of the super's constructor | ||||
* must be: | * must be: | ||||
* | * | ||||
* <ul><code>constructor(Object[] params, <type> cvalue) | |||||
* </code></ul> | |||||
* <pre>constructor(Object[] params, <type> cvalue) | |||||
* </pre> | |||||
* | * | ||||
* <p>Here, <code>cvalue</code> is the constant value specified | * <p>Here, <code>cvalue</code> is the constant value specified | ||||
* by <code>cparam</code>. | * by <code>cparam</code>. | ||||
* <p>If <code>cparam</code> is <code>null</code>, the signature | * <p>If <code>cparam</code> is <code>null</code>, the signature | ||||
* must be: | * must be: | ||||
* | * | ||||
* <ul><code>constructor(Object[] params)</code></ul> | |||||
* <pre>constructor(Object[] params)</pre> | |||||
* | * | ||||
* <p>If <code>body</code> is not null, a copy of that method is | * <p>If <code>body</code> is not null, a copy of that method is | ||||
* embedded in the body of the created constructor. | * embedded in the body of the created constructor. | ||||
* The method specified by <code>body</code> must have the | * The method specified by <code>body</code> must have the | ||||
* signature shown below: | * signature shown below: | ||||
* | * | ||||
* <ul><code>Object method(Object[] params, <type> cvalue) | |||||
* </code></ul> | |||||
* <pre>Object method(Object[] params, <type> cvalue)</pre> | |||||
* | * | ||||
* <p>If <code>cparam</code> is <code>null</code>, the signature | * <p>If <code>cparam</code> is <code>null</code>, the signature | ||||
* must be: | * must be: | ||||
* | * | ||||
* <ul><code>Object method(Object[] params)</code></ul> | |||||
* <pre>Object method(Object[] params)</pre> | |||||
* | * | ||||
* <p>Although the type of the returned value is <code>Object</code>, | * <p>Although the type of the returned value is <code>Object</code>, | ||||
* the value must be always <code>null</code>. | * the value must be always <code>null</code>. | ||||
* | * | ||||
* <p><i>Example:</i> | * <p><i>Example:</i> | ||||
* | * | ||||
* <ul><pre>ClassPool pool = ... ; | |||||
* <pre> | |||||
* ClassPool pool = ... ; | |||||
* CtClass xclass = pool.makeClass("X"); | * CtClass xclass = pool.makeClass("X"); | ||||
* CtMethod method = pool.getMethod("Sample", "m"); | * CtMethod method = pool.getMethod("Sample", "m"); | ||||
* xclass.setSuperclass(pool.get("Y")); | * xclass.setSuperclass(pool.get("Y")); | ||||
* ConstParameter cparam = ConstParameter.string("test"); | * ConstParameter cparam = ConstParameter.string("test"); | ||||
* CtConstructor c = CtNewConstructor.make(argTypes, null, | * CtConstructor c = CtNewConstructor.make(argTypes, null, | ||||
* PASS_PARAMS, method, cparam, xclass); | * PASS_PARAMS, method, cparam, xclass); | ||||
* xclass.addConstructor(c);</pre></ul> | |||||
* xclass.addConstructor(c);</pre> | |||||
* | * | ||||
* <p>where the class <code>Sample</code> is as follows: | * <p>where the class <code>Sample</code> is as follows: | ||||
* | * | ||||
* <ul><pre>public class Sample { | |||||
* <pre> | |||||
* public class Sample { | |||||
* public Object m(Object[] args, String msg) { | * public Object m(Object[] args, String msg) { | ||||
* System.out.println(msg); | * System.out.println(msg); | ||||
* return null; | * return null; | ||||
* } | * } | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>This program produces the following class: | * <p>This program produces the following class: | ||||
* | * | ||||
* <ul><pre>public class X extends Y { | |||||
* <pre> | |||||
* public class X extends Y { | |||||
* public X(int p0) { | * public X(int p0) { | ||||
* super(p0); | * super(p0); | ||||
* String msg = "test"; | * String msg = "test"; | ||||
* Object result = null; | * Object result = null; | ||||
* // end | * // end | ||||
* } | * } | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* @param parameters a list of the parameter types | * @param parameters a list of the parameter types | ||||
* @param exceptions a list of the exceptions | * @param exceptions a list of the exceptions |
* The source code must include not only the method body | * The source code must include not only the method body | ||||
* but the whole declaration, for example, | * but the whole declaration, for example, | ||||
* | * | ||||
* <ul><pre>"public Object id(Object obj) { return obj; }"</pre></ul> | |||||
* <pre>"public Object id(Object obj) { return obj; }"</pre> | |||||
* | * | ||||
* @param src the source text. | * @param src the source text. | ||||
* @param declaring the class to which the created method is added. | * @param declaring the class to which the created method is added. | ||||
* The source code must include not only the method body | * The source code must include not only the method body | ||||
* but the whole declaration, for example, | * but the whole declaration, for example, | ||||
* | * | ||||
* <ul><pre>"public Object id(Object obj) { return obj; }"</pre></ul> | |||||
* <pre>"public Object id(Object obj) { return obj; }"</pre> | |||||
* | * | ||||
* <p>If the source code includes <code>$proceed()</code>, then | * <p>If the source code includes <code>$proceed()</code>, then | ||||
* it is compiled into a method call on the specified object. | * it is compiled into a method call on the specified object. | ||||
* | * | ||||
* <p>The following method is an example of the created method. | * <p>The following method is an example of the created method. | ||||
* | * | ||||
* <ul><pre>int f(int p, int q) { | |||||
* <pre> | |||||
* int f(int p, int q) { | |||||
* return super.f(p, q); | * return super.f(p, q); | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>The name of the created method can be changed by | * <p>The name of the created method can be changed by | ||||
* <code>setName()</code>. | * <code>setName()</code>. | ||||
* | * | ||||
* <p>The method specified by <code>body</code> must have this singature: | * <p>The method specified by <code>body</code> must have this singature: | ||||
* | * | ||||
* <ul><code>Object method(Object[] params, <type> cvalue) | |||||
* </code></ul> | |||||
* <pre>Object method(Object[] params, <type> cvalue)</pre> | |||||
* | * | ||||
* <p>The type of the <code>cvalue</code> depends on | * <p>The type of the <code>cvalue</code> depends on | ||||
* <code>constParam</code>. | * <code>constParam</code>. | ||||
* If <code>constParam</code> is <code>null</code>, the signature | * If <code>constParam</code> is <code>null</code>, the signature | ||||
* must be: | * must be: | ||||
* | * | ||||
* <ul><code>Object method(Object[] params)</code></ul> | |||||
* <pre>Object method(Object[] params)</pre> | |||||
* | * | ||||
* <p>The method body copied from <code>body</code> is wrapped in | * <p>The method body copied from <code>body</code> is wrapped in | ||||
* parameter-conversion code, which converts parameters specified by | * parameter-conversion code, which converts parameters specified by | ||||
* type to the type specified by <code>returnType</code>. Thus, | * type to the type specified by <code>returnType</code>. Thus, | ||||
* the resulting method body is as follows: | * the resulting method body is as follows: | ||||
* | * | ||||
* <ul><pre>Object[] params = new Object[] { p0, p1, ... }; | |||||
* <pre> | |||||
* Object[] params = new Object[] { p0, p1, ... }; | |||||
* <<i>type</i>> cvalue = <<i>constant-value</i>>; | * <<i>type</i>> cvalue = <<i>constant-value</i>>; | ||||
* <i>... copied method body ...</i> | * <i>... copied method body ...</i> | ||||
* Object result = <<i>returned value</i>> | * Object result = <<i>returned value</i>> | ||||
* return (<i><returnType></i>)result; | * return (<i><returnType></i>)result; | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>The variables <code>p0</code>, <code>p2</code>, ... represent | * <p>The variables <code>p0</code>, <code>p2</code>, ... represent | ||||
* formal parameters of the created method. | * formal parameters of the created method. | ||||
* | * | ||||
* <p><i>Example:</i> | * <p><i>Example:</i> | ||||
* | * | ||||
* <ul><pre>ClassPool pool = ... ; | |||||
* <pre> | |||||
* ClassPool pool = ... ; | |||||
* CtClass vec = pool.makeClass("intVector"); | * CtClass vec = pool.makeClass("intVector"); | ||||
* vec.setSuperclass(pool.get("java.util.Vector")); | * vec.setSuperclass(pool.get("java.util.Vector")); | ||||
* CtMethod addMethod = pool.getMethod("Sample", "add0"); | * CtMethod addMethod = pool.getMethod("Sample", "add0"); | ||||
* CtClass[] argTypes = { CtClass.intType }; | * CtClass[] argTypes = { CtClass.intType }; | ||||
* CtMethod m = CtNewMethod.wrapped(CtClass.voidType, "add", argTypes, | * CtMethod m = CtNewMethod.wrapped(CtClass.voidType, "add", argTypes, | ||||
* null, addMethod, null, vec); | * null, addMethod, null, vec); | ||||
* vec.addMethod(m);</pre></ul> | |||||
* vec.addMethod(m);</pre> | |||||
* | * | ||||
* <p>where the class <code>Sample</code> is as follows: | * <p>where the class <code>Sample</code> is as follows: | ||||
* | * | ||||
* <ul><pre>public class Sample extends java.util.Vector { | |||||
* <pre>public class Sample extends java.util.Vector { | |||||
* public Object add0(Object[] args) { | * public Object add0(Object[] args) { | ||||
* super.addElement(args[0]); | * super.addElement(args[0]); | ||||
* return null; | * return null; | ||||
* } | * } | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>This program produces a class <code>intVector</code>: | * <p>This program produces a class <code>intVector</code>: | ||||
* | * | ||||
* <ul><pre>public class intVector extends java.util.Vector { | |||||
* <pre>public class intVector extends java.util.Vector { | |||||
* public void add(int p0) { | * public void add(int p0) { | ||||
* Object[] args = new Object[] { p0 }; | * Object[] args = new Object[] { p0 }; | ||||
* // begin of the copied body | * // begin of the copied body | ||||
* Object result = null; | * Object result = null; | ||||
* // end | * // end | ||||
* } | * } | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>Note that the type of the parameter to <code>add()</code> depends | * <p>Note that the type of the parameter to <code>add()</code> depends | ||||
* only on the value of <code>argTypes</code> passed to | * only on the value of <code>argTypes</code> passed to |
* The startup program of an application using <code>MyTranslator</code> | * The startup program of an application using <code>MyTranslator</code> | ||||
* should be something like this: | * should be something like this: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* import javassist.*; | * import javassist.*; | ||||
* | * | ||||
* public class Main { | * public class Main { | ||||
* cl.run("MyApp", args); | * cl.run("MyApp", args); | ||||
* } | * } | ||||
* } | * } | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>Class <code>MyApp</code> is the main program of the application. | * <p>Class <code>MyApp</code> is the main program of the application. | ||||
* | * | ||||
* <p>This program should be executed as follows: | * <p>This program should be executed as follows: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* % java Main <i>arg1</i> <i>arg2</i>... | * % java Main <i>arg1</i> <i>arg2</i>... | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>It modifies the class <code>MyApp</code> with a <code>MyTranslator</code> | * <p>It modifies the class <code>MyApp</code> with a <code>MyTranslator</code> | ||||
* object before the JVM loads it. | * object before the JVM loads it. | ||||
* | * | ||||
* <p>This program execution is equivalent to: | * <p>This program execution is equivalent to: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* % java MyApp <i>arg1</i> <i>arg2</i>... | * % java MyApp <i>arg1</i> <i>arg2</i>... | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>except that classes are translated by <code>MyTranslator</code> | * <p>except that classes are translated by <code>MyTranslator</code> | ||||
* at load time. | * at load time. | ||||
* unnecessary. For example, if only a class <code>test.Rectangle</code> | * unnecessary. For example, if only a class <code>test.Rectangle</code> | ||||
* is modified, the <code>main()</code> method above will be the following: | * is modified, the <code>main()</code> method above will be the following: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* ClassPool cp = ClassPool.getDefault(); | * ClassPool cp = ClassPool.getDefault(); | ||||
* Loader cl = new Loader(cp); | * Loader cl = new Loader(cp); | ||||
* CtClass ct = cp.get("test.Rectangle"); | * CtClass ct = cp.get("test.Rectangle"); | ||||
* ct.setSuperclass(cp.get("test.Point")); | * ct.setSuperclass(cp.get("test.Point")); | ||||
* cl.run("MyApp", args);</pre></ul> | |||||
* cl.run("MyApp", args);</pre> | |||||
* | * | ||||
* <p>This program changes the super class of the <code>test.Rectangle</code> | * <p>This program changes the super class of the <code>test.Rectangle</code> | ||||
* class. | * class. | ||||
* | * | ||||
* @param args command line parameters. | * @param args command line parameters. | ||||
* <ul> | * <ul> | ||||
* <code>args[0]</code> is the class name to be loaded. | |||||
* <br><code>args[1..n]</code> are parameters passed | |||||
* to the target <code>main()</code>. | |||||
* {@code args[0]} is the class name to be loaded. | |||||
* <br>{@code args[1..n]} are parameters passed | |||||
* to the target {@code main()}. | |||||
* </ul> | * </ul> | ||||
* | * | ||||
* @see javassist.Loader#run(String[]) | * @see javassist.Loader#run(String[]) | ||||
* | * | ||||
* @param args command line parameters. | * @param args command line parameters. | ||||
* <ul> | * <ul> | ||||
* <code>args[0]</code> is the class name to be loaded. | |||||
* <br><code>args[1..n]</code> are parameters passed | |||||
* to the target <code>main()</code>. | |||||
* {@code args[0]} is the class name to be loaded. | |||||
* <br>{@code args[1..n]} are parameters passed | |||||
* to the target {@code main()}. | |||||
* </ul> | * </ul> | ||||
*/ | */ | ||||
public void run(String[] args) throws Throwable { | public void run(String[] args) throws Throwable { |
* Is invoked by a <code>Loader</code> for notifying that | * Is invoked by a <code>Loader</code> for notifying that | ||||
* a class is loaded. The <code>Loader</code> calls | * a class is loaded. The <code>Loader</code> calls | ||||
* | * | ||||
* <ul><pre> | |||||
* pool.get(classname).toBytecode()</pre></ul> | |||||
* <pre> | |||||
* pool.get(classname).toBytecode()</pre> | |||||
* | * | ||||
* to read the class file after <code>onLoad()</code> returns. | * to read the class file after <code>onLoad()</code> returns. | ||||
* | * |
* "org.javassist.test.Main", then the given URL is used for loading that class. | * "org.javassist.test.Main", then the given URL is used for loading that class. | ||||
* The <code>URLClassPath</code> obtains a class file from: | * The <code>URLClassPath</code> obtains a class file from: | ||||
* | * | ||||
* <ul><pre>http://www.javassist.org:80/java/classes/org/javassist/test/Main.class | |||||
* </pre></ul> | |||||
* <pre>http://www.javassist.org:80/java/classes/org/javassist/test/Main.class | |||||
* </pre> | |||||
* | * | ||||
* <p>Here, we assume that <code>host</code> is "www.javassist.org", | * <p>Here, we assume that <code>host</code> is "www.javassist.org", | ||||
* <code>port</code> is 80, and <code>directory</code> is "/java/classes/". | * <code>port</code> is 80, and <code>directory</code> is "/java/classes/". |
* | * | ||||
* <p>For example, if you declare the following annotation type: | * <p>For example, if you declare the following annotation type: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* @interface Author { | * @interface Author { | ||||
* String name() default "Shakespeare"; | * String name() default "Shakespeare"; | ||||
* int age() default 99; | * int age() default 99; | ||||
* } | * } | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>The defautl values of <code>name</code> and <code>age</code> | * <p>The defautl values of <code>name</code> and <code>age</code> | ||||
* are stored as annotation default attributes in <code>Author.class</code>. | * are stored as annotation default attributes in <code>Author.class</code>. | ||||
* The following code snippet obtains the default value of <code>name</code>: | * The following code snippet obtains the default value of <code>name</code>: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* ClassPool pool = ... | * ClassPool pool = ... | ||||
* CtClass cc = pool.get("Author"); | * CtClass cc = pool.get("Author"); | ||||
* CtMethod cm = cc.getDeclaredMethod("age"); | * CtMethod cm = cc.getDeclaredMethod("age"); | ||||
* = (AnnotationDefaultAttribute) | * = (AnnotationDefaultAttribute) | ||||
* minfo.getAttribute(AnnotationDefaultAttribute.tag); | * minfo.getAttribute(AnnotationDefaultAttribute.tag); | ||||
* MemberValue value = ada.getDefaultValue()); // default value of age | * MemberValue value = ada.getDefaultValue()); // default value of age | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>If the following statement is executed after the code above, | * <p>If the following statement is executed after the code above, | ||||
* the default value of age is set to 80: | * the default value of age is set to 80: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* ada.setDefaultValue(new IntegerMemberValue(minfo.getConstPool(), 80)); | * ada.setDefaultValue(new IntegerMemberValue(minfo.getConstPool(), 80)); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* @see AnnotationsAttribute | * @see AnnotationsAttribute | ||||
* @see javassist.bytecode.annotation.MemberValue | * @see javassist.bytecode.annotation.MemberValue |
* | * | ||||
* <p>For example, | * <p>For example, | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* import javassist.bytecode.annotation.Annotation; | * import javassist.bytecode.annotation.Annotation; | ||||
* : | * : | ||||
* CtMethod m = ... ; | * CtMethod m = ... ; | ||||
* Annotation an = attr.getAnnotation("Author"); | * Annotation an = attr.getAnnotation("Author"); | ||||
* String s = ((StringMemberValue)an.getMemberValue("name")).getValue(); | * String s = ((StringMemberValue)an.getMemberValue("name")).getValue(); | ||||
* System.out.println("@Author(name=" + s + ")"); | * System.out.println("@Author(name=" + s + ")"); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>This code snippet retrieves an annotation of the type <code>Author</code> | * <p>This code snippet retrieves an annotation of the type <code>Author</code> | ||||
* from the <code>MethodInfo</code> object specified by <code>minfo</code>. | * from the <code>MethodInfo</code> object specified by <code>minfo</code>. | ||||
* | * | ||||
* <p>If the annotation type <code>Author</code> is annotated by a meta annotation: | * <p>If the annotation type <code>Author</code> is annotated by a meta annotation: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* @Retention(RetentionPolicy.RUNTIME) | * @Retention(RetentionPolicy.RUNTIME) | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>Then <code>Author</code> is visible at runtime. Therefore, the third | * <p>Then <code>Author</code> is visible at runtime. Therefore, the third | ||||
* statement of the code snippet above must be changed into: | * statement of the code snippet above must be changed into: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* AnnotationsAttribute attr = (AnnotationsAttribute) | * AnnotationsAttribute attr = (AnnotationsAttribute) | ||||
* minfo.getAttribute(AnnotationsAttribute.visibleTag); | * minfo.getAttribute(AnnotationsAttribute.visibleTag); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>The attribute tag must be <code>visibleTag</code> instead of | * <p>The attribute tag must be <code>visibleTag</code> instead of | ||||
* <code>invisibleTag</code>. | * <code>invisibleTag</code>. | ||||
* <p>If you want to record a new AnnotationAttribute object, execute the | * <p>If you want to record a new AnnotationAttribute object, execute the | ||||
* following snippet: | * following snippet: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* ClassFile cf = ... ; | * ClassFile cf = ... ; | ||||
* ConstPool cp = cf.getConstPool(); | * ConstPool cp = cf.getConstPool(); | ||||
* AnnotationsAttribute attr | * AnnotationsAttribute attr | ||||
* attr.setAnnotation(a); | * attr.setAnnotation(a); | ||||
* cf.addAttribute(attr); | * cf.addAttribute(attr); | ||||
* cf.setVersionToJava5(); | * cf.setVersionToJava5(); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>The last statement is necessary if the class file was produced by | * <p>The last statement is necessary if the class file was produced by | ||||
* <code>javac</code> of JDK 1.4 or earlier. Otherwise, it is not necessary. | * <code>javac</code> of JDK 1.4 or earlier. Otherwise, it is not necessary. | ||||
/** | /** | ||||
* Changes the annotations. A call to this method is equivalent to: | * Changes the annotations. A call to this method is equivalent to: | ||||
* <ul><pre>setAnnotations(new Annotation[] { annotation })</pre></ul> | |||||
* <pre>setAnnotations(new Annotation[] { annotation })</pre> | |||||
* | * | ||||
* @param annotation the data structure representing | * @param annotation the data structure representing | ||||
* the new annotation. | * the new annotation. |
* <p>A <code>Bytecode</code> object is an unbounded array | * <p>A <code>Bytecode</code> object is an unbounded array | ||||
* containing bytecode. For example, | * containing bytecode. For example, | ||||
* | * | ||||
* <ul><pre>ConstPool cp = ...; // constant pool table | |||||
* <pre> | |||||
* ConstPool cp = ...; // constant pool table | |||||
* Bytecode b = new Bytecode(cp, 1, 0); | * Bytecode b = new Bytecode(cp, 1, 0); | ||||
* b.addIconst(3); | * b.addIconst(3); | ||||
* b.addReturn(CtClass.intType); | * b.addReturn(CtClass.intType); | ||||
* CodeAttribute ca = b.toCodeAttribute();</ul></pre> | |||||
* CodeAttribute ca = b.toCodeAttribute();</pre> | |||||
* | * | ||||
* <p>This program produces a Code attribute including a bytecode | * <p>This program produces a Code attribute including a bytecode | ||||
* sequence: | * sequence: | ||||
* | * | ||||
* <ul><pre>iconst_3 | |||||
* ireturn</pre></ul> | |||||
* <pre> | |||||
* iconst_3 | |||||
* ireturn</pre> | |||||
* | * | ||||
* @see ConstPool | * @see ConstPool | ||||
* @see CodeAttribute | * @see CodeAttribute |
* | * | ||||
* <p>The returned value is obtained from <code>inner_class_access_flags</code> | * <p>The returned value is obtained from <code>inner_class_access_flags</code> | ||||
* of the entry representing this nested class itself | * of the entry representing this nested class itself | ||||
* in <code>InnerClasses_attribute</code>>. | |||||
* in <code>InnerClasses_attribute</code>. | |||||
*/ | */ | ||||
public int getInnerAccessFlags() { | public int getInnerAccessFlags() { | ||||
InnerClassesAttribute ica | InnerClassesAttribute ica |
public static boolean doPreverify = false; | public static boolean doPreverify = false; | ||||
/** | /** | ||||
* The name of constructors: <code><init></code>. | |||||
* The name of constructors: <code><init></code>. | |||||
*/ | */ | ||||
public static final String nameInit = "<init>"; | public static final String nameInit = "<init>"; | ||||
/** | /** | ||||
* The name of class initializer (static initializer): | * The name of class initializer (static initializer): | ||||
* <code><clinit></code>. | |||||
* <code><clinit></code>. | |||||
*/ | */ | ||||
public static final String nameClinit = "<clinit>"; | public static final String nameClinit = "<clinit>"; | ||||
/** | /** | ||||
* Constructs a <code>TypeParameter</code> representing a type parametre | * Constructs a <code>TypeParameter</code> representing a type parametre | ||||
* like <code><T extends ... ><code>. | |||||
* like <code><T extends ... ></code>. | |||||
* | * | ||||
* @param name parameter name. | * @param name parameter name. | ||||
* @param superClass an upper bound class-type (or null). | * @param superClass an upper bound class-type (or null). | ||||
/** | /** | ||||
* Constructs a <code>TypeParameter</code> representing a type parameter | * Constructs a <code>TypeParameter</code> representing a type parameter | ||||
* like <code><T><code>. | |||||
* like <code><T></code>. | |||||
* | * | ||||
* @param name parameter name. | * @param name parameter name. | ||||
*/ | */ |
* | * | ||||
* @param pos the position. | * @param pos the position. | ||||
* @param offsetDelta | * @param offsetDelta | ||||
* @param k the <cod>k</code> last locals are absent. | |||||
* @param k the <code>k</code> last locals are absent. | |||||
*/ | */ | ||||
public void chopFrame(int pos, int offsetDelta, int k) throws BadBytecode {} | public void chopFrame(int pos, int offsetDelta, int k) throws BadBytecode {} | ||||
* @param offsetDelta | * @param offsetDelta | ||||
* @param tags <code>locals[i].tag</code>. | * @param tags <code>locals[i].tag</code>. | ||||
* @param data <code>locals[i].cpool_index</code> | * @param data <code>locals[i].cpool_index</code> | ||||
* or <cod>locals[i].offset</code>. | |||||
* or <code>locals[i].offset</code>. | |||||
*/ | */ | ||||
public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) | public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) | ||||
throws BadBytecode {} | throws BadBytecode {} | ||||
* @param tag <code>stack[0].tag</code>. | * @param tag <code>stack[0].tag</code>. | ||||
* @param data <code>stack[0].cpool_index</code> | * @param data <code>stack[0].cpool_index</code> | ||||
* if the tag is <code>OBJECT</code>, | * if the tag is <code>OBJECT</code>, | ||||
* or <cod>stack[0].offset</code> | |||||
* or <code>stack[0].offset</code> | |||||
* if the tag is <code>UNINIT</code>. | * if the tag is <code>UNINIT</code>. | ||||
* Otherwise, this parameter is not used. | * Otherwise, this parameter is not used. | ||||
*/ | */ | ||||
* either 1, 2, or 3. | * either 1, 2, or 3. | ||||
* @param data <code>locals[].cpool_index</code> | * @param data <code>locals[].cpool_index</code> | ||||
* if the tag is <code>OBJECT</code>, | * if the tag is <code>OBJECT</code>, | ||||
* or <cod>locals[].offset</code> | |||||
* or <code>locals[].offset</code> | |||||
* if the tag is <code>UNINIT</code>. | * if the tag is <code>UNINIT</code>. | ||||
* Otherwise, this parameter is not used. | * Otherwise, this parameter is not used. | ||||
*/ | */ | ||||
* @param localTags <code>locals[].tag</code>. | * @param localTags <code>locals[].tag</code>. | ||||
* @param localData <code>locals[].cpool_index</code> | * @param localData <code>locals[].cpool_index</code> | ||||
* if the tag is <code>OBJECT</code>, | * if the tag is <code>OBJECT</code>, | ||||
* or <cod>locals[].offset</code> | |||||
* or <code>locals[].offset</code> | |||||
* if the tag is <code>UNINIT</code>. | * if the tag is <code>UNINIT</code>. | ||||
* Otherwise, this parameter is not used. | * Otherwise, this parameter is not used. | ||||
* @param stackTags <code>stack[].tag</code>. | * @param stackTags <code>stack[].tag</code>. | ||||
* @param stackData <code>stack[].cpool_index</code> | * @param stackData <code>stack[].cpool_index</code> | ||||
* if the tag is <code>OBJECT</code>, | * if the tag is <code>OBJECT</code>, | ||||
* or <cod>stack[].offset</code> | |||||
* or <code>stack[].offset</code> | |||||
* if the tag is <code>UNINIT</code>. | * if the tag is <code>UNINIT</code>. | ||||
* Otherwise, this parameter is not used. | * Otherwise, this parameter is not used. | ||||
*/ | */ |
* A class representing | * A class representing | ||||
* {@code RuntimeVisibleTypeAnnotations} attribute and | * {@code RuntimeVisibleTypeAnnotations} attribute and | ||||
* {@code RuntimeInvisibleTypeAnnotations} attribute. | * {@code RuntimeInvisibleTypeAnnotations} attribute. | ||||
* | |||||
* @since 3.19 | |||||
*/ | */ | ||||
public class TypeAnnotationsAttribute extends AttributeInfo { | public class TypeAnnotationsAttribute extends AttributeInfo { | ||||
/** | /** |
* // Method to analyze | * // Method to analyze | ||||
* public Object doSomething(int x) { | * public Object doSomething(int x) { | ||||
* Number n; | * Number n; | ||||
* if (x < 5) { | |||||
* if (x < 5) { | |||||
* n = new Double(0); | * n = new Double(0); | ||||
* } else { | * } else { | ||||
* n = new Long(0); | * n = new Long(0); |
* | * | ||||
* <p>The following code snippet is an example of use of this class: | * <p>The following code snippet is an example of use of this class: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* ConstPool pool = ...; | * ConstPool pool = ...; | ||||
* output = new ByteArrayOutputStream(); | * output = new ByteArrayOutputStream(); | ||||
* writer = new AnnotationsWriter(output, pool); | * writer = new AnnotationsWriter(output, pool); | ||||
* AnnotationsAttribute anno | * AnnotationsAttribute anno | ||||
* = new AnnotationsAttribute(pool, AnnotationsAttribute.visibleTag, | * = new AnnotationsAttribute(pool, AnnotationsAttribute.visibleTag, | ||||
* attribute_info); | * attribute_info); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>The code snippet above generates the annotation attribute | * <p>The code snippet above generates the annotation attribute | ||||
* corresponding to this annotation: | * corresponding to this annotation: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* @Author(name = "chiba", address = "tokyo") | * @Author(name = "chiba", address = "tokyo") | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* @see javassist.bytecode.AnnotationsAttribute | * @see javassist.bytecode.AnnotationsAttribute | ||||
* @see javassist.bytecode.ParameterAnnotationsAttribute | * @see javassist.bytecode.ParameterAnnotationsAttribute |
* A convenience class for constructing a | * A convenience class for constructing a | ||||
* {@code ..TypeAnnotations_attribute}. | * {@code ..TypeAnnotations_attribute}. | ||||
* See the source code of the {@link javassist.bytecode.TypeAnnotationsAttribute} class. | * See the source code of the {@link javassist.bytecode.TypeAnnotationsAttribute} class. | ||||
* | |||||
* @since 3.19 | |||||
*/ | */ | ||||
public class TypeAnnotationsWriter extends AnnotationsWriter { | public class TypeAnnotationsWriter extends AnnotationsWriter { | ||||
/** | /** |
* | * | ||||
* <p>The following code is an example: | * <p>The following code is an example: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* CtMethod cm = ...; | * CtMethod cm = ...; | ||||
* cm.instrument(new ExprEditor() { | * cm.instrument(new ExprEditor() { | ||||
* public void edit(MethodCall m) throws CannotCompileException { | * public void edit(MethodCall m) throws CannotCompileException { | ||||
* + m.getLineNumber()); | * + m.getLineNumber()); | ||||
* } | * } | ||||
* }); | * }); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>This code inspects all method calls appearing in the method represented | * <p>This code inspects all method calls appearing in the method represented | ||||
* by <code>cm</code> and it prints the names and the line numbers of the | * by <code>cm</code> and it prints the names and the line numbers of the |
* Specifies how a <code>java.lang.Class</code> object is loaded. | * Specifies how a <code>java.lang.Class</code> object is loaded. | ||||
* | * | ||||
* <p>If true, it is loaded by: | * <p>If true, it is loaded by: | ||||
* <ul><pre>Thread.currentThread().getContextClassLoader().loadClass()</pre></ul> | |||||
* <pre>Thread.currentThread().getContextClassLoader().loadClass()</pre> | |||||
* <p>If false, it is loaded by <code>Class.forName()</code>. | * <p>If false, it is loaded by <code>Class.forName()</code>. | ||||
* The default value is false. | * The default value is false. | ||||
*/ | */ |
* the class file is broken. | * the class file is broken. | ||||
* | * | ||||
* <p>For example, | * <p>For example, | ||||
* <ul><pre>% java javassist.tools.Dump foo.class</pre></ul> | |||||
* <pre>% java javassist.tools.Dump foo.class</pre> | |||||
* | * | ||||
* <p>prints the contents of the constant pool and the list of methods | * <p>prints the contents of the constant pool and the list of methods | ||||
* and fields. | * and fields. |
* of all methods in a class. | * of all methods in a class. | ||||
* | * | ||||
* <p>For example, | * <p>For example, | ||||
* <ul><pre>% java javassist.tools.framedump foo.class</pre></ul> | |||||
* <pre>% java javassist.tools.framedump foo.class</pre> | |||||
*/ | */ | ||||
public class framedump { | public class framedump { | ||||
private framedump() {} | private framedump() {} |
* <p>To obtain a class metaobject, calls <code>_getClass()</code> | * <p>To obtain a class metaobject, calls <code>_getClass()</code> | ||||
* on a reflective object. For example, | * on a reflective object. For example, | ||||
* | * | ||||
* <ul><pre>ClassMetaobject cm = ((Metalevel)reflectiveObject)._getClass(); | |||||
* </pre></ul> | |||||
* <pre>ClassMetaobject cm = ((Metalevel)reflectiveObject)._getClass(); | |||||
* </pre> | |||||
* | * | ||||
* @see javassist.tools.reflect.Metaobject | * @see javassist.tools.reflect.Metaobject | ||||
* @see javassist.tools.reflect.Metalevel | * @see javassist.tools.reflect.Metalevel | ||||
* Specifies how a <code>java.lang.Class</code> object is loaded. | * Specifies how a <code>java.lang.Class</code> object is loaded. | ||||
* | * | ||||
* <p>If true, it is loaded by: | * <p>If true, it is loaded by: | ||||
* <ul><pre>Thread.currentThread().getContextClassLoader().loadClass()</pre></ul> | |||||
* <pre>Thread.currentThread().getContextClassLoader().loadClass()</pre> | |||||
* <p>If false, it is loaded by <code>Class.forName()</code>. | * <p>If false, it is loaded by <code>Class.forName()</code>. | ||||
* The default value is false. | * The default value is false. | ||||
*/ | */ | ||||
* original name. | * original name. | ||||
* | * | ||||
* <p>This method is useful, in conjuction with | * <p>This method is useful, in conjuction with | ||||
* <link>ClassMetaobject#getMethod()</link>, to obtain a quick reference | |||||
* {@link ClassMetaobject#getMethod()}, to obtain a quick reference | |||||
* to the original method in the reflected class (i.e. not the proxy | * to the original method in the reflected class (i.e. not the proxy | ||||
* method), using the original name of the method. | * method), using the original name of the method. | ||||
* | * |
* by that class name is not reflective. | * by that class name is not reflective. | ||||
* | * | ||||
* <p>For example, | * <p>For example, | ||||
* <ul><pre>% java Compiler Dog -m MetaDog -c CMetaDog Cat -m MetaCat Cow | |||||
* </pre></ul> | |||||
* <pre>% java Compiler Dog -m MetaDog -c CMetaDog Cat -m MetaCat Cow | |||||
* </pre> | |||||
* | * | ||||
* <p>modifies class files <code>Dog.class</code>, <code>Cat.class</code>, | * <p>modifies class files <code>Dog.class</code>, <code>Cat.class</code>, | ||||
* and <code>Cow.class</code>. | * and <code>Cow.class</code>. |
* including a reflective class, | * including a reflective class, | ||||
* you must write a start-up program as follows: | * you must write a start-up program as follows: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* public class Main { | * public class Main { | ||||
* public static void main(String[] args) throws Throwable { | * public static void main(String[] args) throws Throwable { | ||||
* javassist.tools.reflect.Loader cl | * javassist.tools.reflect.Loader cl | ||||
* cl.run("MyApp", args); | * cl.run("MyApp", args); | ||||
* } | * } | ||||
* } | * } | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>Then run this program as follows: | * <p>Then run this program as follows: | ||||
* | * | ||||
* <ul><pre>% java javassist.tools.reflect.Loader Main arg1, ...</pre></ul> | |||||
* <pre>% java javassist.tools.reflect.Loader Main arg1, ...</pre> | |||||
* | * | ||||
* <p>This command runs <code>Main.main()</code> with <code>arg1</code>, ... | * <p>This command runs <code>Main.main()</code> with <code>arg1</code>, ... | ||||
* and <code>Main.main()</code> runs <code>MyApp.main()</code> with | * and <code>Main.main()</code> runs <code>MyApp.main()</code> with | ||||
* | * | ||||
* <p>Also, you can run <code>MyApp</code> in a slightly different way: | * <p>Also, you can run <code>MyApp</code> in a slightly different way: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* public class Main2 { | * public class Main2 { | ||||
* public static void main(String[] args) throws Throwable { | * public static void main(String[] args) throws Throwable { | ||||
* javassist.tools.reflect.Loader cl = new javassist.tools.reflect.Loader(); | * javassist.tools.reflect.Loader cl = new javassist.tools.reflect.Loader(); | ||||
* cl.run("MyApp", args); | * cl.run("MyApp", args); | ||||
* } | * } | ||||
* } | * } | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>This program is run as follows: | * <p>This program is run as follows: | ||||
* | * | ||||
* <ul><pre>% java Main2 arg1, ...</pre></ul> | |||||
* <pre>% java Main2 arg1, ...</pre> | |||||
* | * | ||||
* <p>The difference from the former one is that the class <code>Main</code> | * <p>The difference from the former one is that the class <code>Main</code> | ||||
* is loaded by <code>javassist.tools.reflect.Loader</code> whereas the class | * is loaded by <code>javassist.tools.reflect.Loader</code> whereas the class | ||||
* | * | ||||
* <p>The class <code>Main2</code> is equivalent to this class: | * <p>The class <code>Main2</code> is equivalent to this class: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* public class Main3 { | * public class Main3 { | ||||
* public static void main(String[] args) throws Throwable { | * public static void main(String[] args) throws Throwable { | ||||
* Reflection reflection = new Reflection(); | * Reflection reflection = new Reflection(); | ||||
* cl.run("MyApp", args); | * cl.run("MyApp", args); | ||||
* } | * } | ||||
* } | * } | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p><b>Note:</b> | * <p><b>Note:</b> | ||||
* | * |
* <p>To obtain a metaobject, calls <code>_getMetaobject()</code> | * <p>To obtain a metaobject, calls <code>_getMetaobject()</code> | ||||
* on a reflective object. For example, | * on a reflective object. For example, | ||||
* | * | ||||
* <ul><pre>Metaobject m = ((Metalevel)reflectiveObject)._getMetaobject(); | |||||
* </pre></ul> | |||||
* <pre> | |||||
* Metaobject m = ((Metalevel)reflectiveObject)._getMetaobject(); | |||||
* </pre> | |||||
* | * | ||||
* @see javassist.tools.reflect.ClassMetaobject | * @see javassist.tools.reflect.ClassMetaobject | ||||
* @see javassist.tools.reflect.Metalevel | * @see javassist.tools.reflect.Metalevel | ||||
* <p>Note: this method is not invoked if the base-level method | * <p>Note: this method is not invoked if the base-level method | ||||
* is invoked by a constructor in the super class. For example, | * is invoked by a constructor in the super class. For example, | ||||
* | * | ||||
* <ul><pre>abstract class A { | |||||
* <pre> | |||||
* abstract class A { | |||||
* abstract void initialize(); | * abstract void initialize(); | ||||
* A() { | * A() { | ||||
* initialize(); // not intercepted | * initialize(); // not intercepted | ||||
* super(); | * super(); | ||||
* initialize(); // intercepted | * initialize(); // intercepted | ||||
* } | * } | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>if an instance of B is created, | * <p>if an instance of B is created, | ||||
* the invocation of initialize() in B is intercepted only once. | * the invocation of initialize() in B is intercepted only once. |
* | * | ||||
* <p>To do this, the original class file representing a reflective class: | * <p>To do this, the original class file representing a reflective class: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* class Person { | * class Person { | ||||
* public int f(int i) { return i + 1; } | * public int f(int i) { return i + 1; } | ||||
* public int value; | * public int value; | ||||
* } | * } | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>is modified so that it represents a class: | * <p>is modified so that it represents a class: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* class Person implements Metalevel { | * class Person implements Metalevel { | ||||
* public int _original_f(int i) { return i + 1; } | * public int _original_f(int i) { return i + 1; } | ||||
* public int f(int i) { <i>delegate to the metaobject</i> } | * public int f(int i) { <i>delegate to the metaobject</i> } | ||||
* public Metaobject _getMetaobject() { <i>return a metaobject</i> } | * public Metaobject _getMetaobject() { <i>return a metaobject</i> } | ||||
* public void _setMetaobject(Metaobject m) { <i>change a metaobject</i> } | * public void _setMetaobject(Metaobject m) { <i>change a metaobject</i> } | ||||
* } | * } | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* @see javassist.tools.reflect.ClassMetaobject | * @see javassist.tools.reflect.ClassMetaobject | ||||
* @see javassist.tools.reflect.Metaobject | * @see javassist.tools.reflect.Metaobject |
* <p>If you run a program with <code>javassist.tools.web.Viewer</code>, | * <p>If you run a program with <code>javassist.tools.web.Viewer</code>, | ||||
* you can construct an object importer as follows: | * you can construct an object importer as follows: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* Viewer v = (Viewer)this.getClass().getClassLoader(); | * Viewer v = (Viewer)this.getClass().getClassLoader(); | ||||
* ObjectImporter oi = new ObjectImporter(v.getServer(), v.getPort()); | * ObjectImporter oi = new ObjectImporter(v.getServer(), v.getPort()); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* @see javassist.tools.web.Viewer | * @see javassist.tools.web.Viewer | ||||
*/ | */ |
* | * | ||||
* <p>The proxy class for class A is as follows: | * <p>The proxy class for class A is as follows: | ||||
* | * | ||||
* <ul><pre>public class A implements Proxy, Serializable { | |||||
* <pre>public class A implements Proxy, Serializable { | |||||
* private ObjectImporter importer; | * private ObjectImporter importer; | ||||
* private int objectId; | * private int objectId; | ||||
* public int _getObjectId() { return objectId; } | * public int _getObjectId() { return objectId; } | ||||
* } | * } | ||||
* | * | ||||
* ... the same methods that the original class A declares ... | * ... the same methods that the original class A declares ... | ||||
* }</pre></ul> | |||||
* }</pre> | |||||
* | * | ||||
* <p>Instances of the proxy class is created by an | * <p>Instances of the proxy class is created by an | ||||
* <code>ObjectImporter</code> object. | * <code>ObjectImporter</code> object. |
* | * | ||||
* <p>To run, you should type: | * <p>To run, you should type: | ||||
* | * | ||||
* <ul><code>% java javassist.tools.web.Viewer <i>host port</i> Main arg1, ...</code></ul> | |||||
* <pre>% java javassist.tools.web.Viewer <i>host port</i> Main arg1, ...</pre> | |||||
* | * | ||||
* <p>This command calls <code>Main.main()</code> with <code>arg1,...</code> | * <p>This command calls <code>Main.main()</code> with <code>arg1,...</code> | ||||
* All classes including <code>Main</code> are fetched from | * All classes including <code>Main</code> are fetched from | ||||
* a program loaded by this object can call a method in <code>Viewer</code>. | * a program loaded by this object can call a method in <code>Viewer</code>. | ||||
* For example, you can write something like this: | * For example, you can write something like this: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* Viewer v = (Viewer)this.getClass().getClassLoader(); | * Viewer v = (Viewer)this.getClass().getClassLoader(); | ||||
* String port = v.getPort(); | * String port = v.getPort(); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
*/ | */ | ||||
public class Viewer extends ClassLoader { | public class Viewer extends ClassLoader { |
/** | /** | ||||
* A utility class for dynamically reloading a class by | * A utility class for dynamically reloading a class by | ||||
* the Java Platform Debugger Architecture (JPDA), or <it>HotSwap</code>. | |||||
* the Java Platform Debugger Architecture (JPDA), or <i>HotSwap</i>. | |||||
* It works only with JDK 1.4 and later. | * It works only with JDK 1.4 and later. | ||||
* | * | ||||
* <p><b>Note:</b> The new definition of the reloaded class must declare | * <p><b>Note:</b> The new definition of the reloaded class must declare | ||||
* <p>To use this class, the JVM must be launched with the following | * <p>To use this class, the JVM must be launched with the following | ||||
* command line options: | * command line options: | ||||
* | * | ||||
* <ul> | |||||
* <p>For Java 1.4,<br> | * <p>For Java 1.4,<br> | ||||
* <pre>java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000</pre> | * <pre>java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000</pre> | ||||
* <p>For Java 5,<br> | * <p>For Java 5,<br> | ||||
* <pre>java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000</pre> | * <pre>java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000</pre> | ||||
* </ul> | |||||
* | * | ||||
* <p>Note that 8000 is the port number used by <code>HotSwapper</code>. | * <p>Note that 8000 is the port number used by <code>HotSwapper</code>. | ||||
* Any port number can be specified. Since <code>HotSwapper</code> does not | * Any port number can be specified. Since <code>HotSwapper</code> does not | ||||
* | * | ||||
* <p>Using <code>HotSwapper</code> is easy. See the following example: | * <p>Using <code>HotSwapper</code> is easy. See the following example: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* CtClass clazz = ... | * CtClass clazz = ... | ||||
* byte[] classFile = clazz.toBytecode(); | * byte[] classFile = clazz.toBytecode(); | ||||
* HotSwapper hs = new HostSwapper(8000); // 8000 is a port number. | * HotSwapper hs = new HostSwapper(8000); // 8000 is a port number. | ||||
* hs.reload("Test", classFile); | * hs.reload("Test", classFile); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p><code>reload()</code> | * <p><code>reload()</code> | ||||
* first unload the <code>Test</code> class and load a new version of | * first unload the <code>Test</code> class and load a new version of |
* | * | ||||
* <p>For example, if the following code is executed, | * <p>For example, if the following code is executed, | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* ProxyFactory f = new ProxyFactory(); | * ProxyFactory f = new ProxyFactory(); | ||||
* f.setSuperclass(Foo.class); | * f.setSuperclass(Foo.class); | ||||
* f.setFilter(new MethodFilter() { | * f.setFilter(new MethodFilter() { | ||||
* }; | * }; | ||||
* Foo foo = (Foo)c.newInstance(); | * Foo foo = (Foo)c.newInstance(); | ||||
* ((Proxy)foo).setHandler(mi); | * ((Proxy)foo).setHandler(mi); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>Here, <code>Method</code> is <code>java.lang.reflect.Method</code>.</p> | * <p>Here, <code>Method</code> is <code>java.lang.reflect.Method</code>.</p> | ||||
* | * | ||||
* <code>mi</code> and prints a message before executing the originally called method | * <code>mi</code> and prints a message before executing the originally called method | ||||
* <code>bar()</code> in <code>Foo</code>. | * <code>bar()</code> in <code>Foo</code>. | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* foo.bar(); | * foo.bar(); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>The last three lines of the code shown above can be replaced with a call to | * <p>The last three lines of the code shown above can be replaced with a call to | ||||
* the helper method <code>create</code>, which generates a proxy class, instantiates | * the helper method <code>create</code>, which generates a proxy class, instantiates | ||||
* it, and sets the method handler of the instance: | * it, and sets the method handler of the instance: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* : | * : | ||||
* Foo foo = (Foo)f.create(new Class[0], new Object[0], mi); | * Foo foo = (Foo)f.create(new Class[0], new Object[0], mi); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>To change the method handler during runtime, | * <p>To change the method handler during runtime, | ||||
* execute the following code: | * execute the following code: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* MethodHandler mi = ... ; // alternative handler | * MethodHandler mi = ... ; // alternative handler | ||||
* ((Proxy)foo).setHandler(mi); | * ((Proxy)foo).setHandler(mi); | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p> If setHandler is never called for a proxy instance then it will | * <p> If setHandler is never called for a proxy instance then it will | ||||
* employ the default handler which proceeds by invoking the original method. | * employ the default handler which proceeds by invoking the original method. | ||||
* The behaviour of the default handler is identical to the following | * The behaviour of the default handler is identical to the following | ||||
* handler: | * handler: | ||||
* | * | ||||
* <ul><pre> | |||||
* <pre> | |||||
* class EmptyHandler implements MethodHandler { | * class EmptyHandler implements MethodHandler { | ||||
* public Object invoke(Object self, Method m, | * public Object invoke(Object self, Method m, | ||||
* Method proceed, Object[] args) throws Exception { | * Method proceed, Object[] args) throws Exception { | ||||
* return proceed.invoke(self, args); | * return proceed.invoke(self, args); | ||||
* } | * } | ||||
* } | * } | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* <p>A proxy factory caches and reuses proxy classes by default. It is possible to reset | * <p>A proxy factory caches and reuses proxy classes by default. It is possible to reset | ||||
* this default globally by setting static field {@link ProxyFactory#useCache} to false. | * this default globally by setting static field {@link ProxyFactory#useCache} to false. | ||||
* implementation. | * implementation. | ||||
* | * | ||||
* <p>Example: | * <p>Example: | ||||
* <ul><pre> | |||||
* <pre> | |||||
* ProxyFactory.classLoaderProvider = new ProxyFactory.ClassLoaderProvider() { | * ProxyFactory.classLoaderProvider = new ProxyFactory.ClassLoaderProvider() { | ||||
* public ClassLoader get(ProxyFactory pf) { | * public ClassLoader get(ProxyFactory pf) { | ||||
* return Thread.currentThread().getContextClassLoader(); | * return Thread.currentThread().getContextClassLoader(); | ||||
* } | * } | ||||
* }; | * }; | ||||
* </pre></ul> | |||||
* </pre> | |||||
* | * | ||||
* @since 3.4 | * @since 3.4 | ||||
*/ | */ |