diff options
-rw-r--r-- | Readme.html | 2 | ||||
-rw-r--r-- | build.xml | 2 | ||||
-rw-r--r-- | src/main/META-INF/MANIFEST.MF | 2 | ||||
-rw-r--r-- | src/main/javassist/ClassPool.java | 2 | ||||
-rw-r--r-- | src/main/javassist/bytecode/StackMapTable.java | 424 |
5 files changed, 289 insertions, 143 deletions
diff --git a/Readme.html b/Readme.html index 20945b60..a7715eee 100644 --- a/Readme.html +++ b/Readme.html @@ -281,7 +281,7 @@ see javassist.Dump. <h2>Changes</h2> -<p>-version 3.4 +<p>-version 3.4 on November 17, 2006 <ul> <li>A bug in CodeConverter#replaceFieldRead() and CodeConverter#replaceFieldWrite() was fixed. <a href="http://jira.jboss.com/jira/browse/JBAOP-284">JBAOP-284</a>. @@ -6,7 +6,7 @@ <project name="javassist" default="jar" basedir="."> - <property name="dist-version" value="javassist-3.3"/> + <property name="dist-version" value="javassist-3.4"/> <property environment="env"/> <property name="target.jar" value="javassist.jar"/> diff --git a/src/main/META-INF/MANIFEST.MF b/src/main/META-INF/MANIFEST.MF index ee63d0b8..03f31f13 100644 --- a/src/main/META-INF/MANIFEST.MF +++ b/src/main/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.1 Specification-Title: Javassist Created-By: Shigeru Chiba, Tokyo Institute of Technology Specification-Vendor: Shigeru Chiba, Tokyo Institute of Technology -Specification-Version: 3.3 +Specification-Version: 3.4 Main-Class: javassist.CtClass Name: javassist/ diff --git a/src/main/javassist/ClassPool.java b/src/main/javassist/ClassPool.java index 1a487cd3..1b84ec4b 100644 --- a/src/main/javassist/ClassPool.java +++ b/src/main/javassist/ClassPool.java @@ -874,7 +874,7 @@ public class ClassPool { * If it is null, the default domain created * by <code>java.lang.ClassLoader</code> is used. * - * @see #getContextClassLoader() + * @see #getClassLoader() * @since 3.3 */ public Class toClass(CtClass ct, ClassLoader loader, ProtectionDomain domain) diff --git a/src/main/javassist/bytecode/StackMapTable.java b/src/main/javassist/bytecode/StackMapTable.java index 7a56c633..2e1cf156 100644 --- a/src/main/javassist/bytecode/StackMapTable.java +++ b/src/main/javassist/bytecode/StackMapTable.java @@ -17,9 +17,9 @@ package javassist.bytecode; import java.io.DataInputStream; import java.io.DataOutputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Map; -import java.util.ArrayList; /** * <code>stack_map</code> attribute. @@ -27,6 +27,8 @@ import java.util.ArrayList; * <p>This is an entry in the attributes table of a Code attribute. * It was introduced by J2SE 6 for the process of verification by * typechecking. + * + * @since 3.4 */ public class StackMapTable extends AttributeInfo { /** @@ -34,32 +36,23 @@ public class StackMapTable extends AttributeInfo { */ public static final String tag = "StackMapTable"; - private ArrayList entries; // ArrayList<StackMapFrame>. may be null. - /** * Constructs a <code>stack_map</code> attribute. */ - public StackMapTable(ConstPool cp) { - this(cp, (byte[])null); - } - private StackMapTable(ConstPool cp, byte[] newInfo) { super(cp, tag, newInfo); - entries = null; } StackMapTable(ConstPool cp, int name_id, DataInputStream in) throws IOException { super(cp, name_id, in); - entries = null; } /** * Makes a copy. */ public AttributeInfo copy(ConstPool newCp, Map classnames) { - toByteArray(false); int s = info.length; byte[] newInfo = new byte[s]; System.arraycopy(info, 0, newInfo, 0, s); @@ -67,48 +60,9 @@ public class StackMapTable extends AttributeInfo { } void write(DataOutputStream out) throws IOException { - toByteArray(true); super.write(out); } - private void parseMap() { - byte[] data = info; - int n = ByteArray.readU16bit(data, 0); - entries = new ArrayList(n); - int offset = 2; - while (n-- > 0) { - int frameType; - } - - } - - private void toByteArray(boolean clear) { - if (entries != null) - ; // unparse - } - - /** - * <code>union stack_map_frame</code>. - * <p><code>verification_type_info</code> is represented - * by a pair of two <code>int</code> values. No class - * for represening <code>verification_type_ - */ - public static class StackMapFrame { - /** - * <code>u2 offset_delta</code>. - * If <code>offset_delta</code> is not included - * (i.e. <code>same_frame</code>), the value of - * this field is computed from other members such - * as <code>frame_type</code>. - */ - public int offsetDelta; - } - - /* - * verification_type_info is represented by a pair of - * 2 int variables (tag and cpool_index/offset). - */ - /** * <code>Top_variable_info.tag</code>. */ @@ -155,150 +109,342 @@ public class StackMapTable extends AttributeInfo { public static final int UNINIT = 8; /** - * <code>same_frame</code>. - * <code>frame_type</code> is not included. - * It is computed by <code>offsetDelta</code>. + * A code walker for a StackMapTable attribute. */ - public static class SameFrame extends StackMapFrame { - /** - * The maximum value of <code>SAME</code>. - */ - public static final int FRAME_TYPE_MAX = 63; - } + static class Walker { + byte[] info; + int numOfEntries; - /** - * <code>same_locals_1_stack_item_frame</code> or - * <code>same_locals_1_stack_item_frame_extended</code>. - * - * <p><code>frame_type</code> is not included. - * It is computed by <code>offsetDelta</code>. - */ - public static class SameLocals extends StackMapFrame { /** - * The minimum value of <code>SAME_LOCALS_1_STACK_ITEM</code>. + * Constructs a walker. + * + * @param data the <code>info</code> field of the + * <code>attribute_info</code> structure. */ - public static final int FRAME_TYPE = 64; + public Walker(byte[] data) { + info = data; + numOfEntries = ByteArray.readU16bit(data, 0); + } /** - * The maximum value of <code>SAME_LOCALS_1_STACK_ITEM</code>. + * Returns the number of the entries. */ - public static final int FRAME_TYPE_MAX = 127; + public final int size() { return numOfEntries; } /** - * <code>SAME_LOCALS_1_STACK_ITEM_EXTENDED</code>. + * Visits each entry of the stack map frames. */ - public static final int FRAME_TYPE_EXTENDED = 247; + public final void parse() throws BadBytecode { + int n = numOfEntries; + int pos = 2; + for (int i = 0; i < n; i++) + pos = stackMapFrames(pos, i); + } /** - * <code>stack[0].tag</code>. + * Invoked when the next entry of the stack map frames is visited. + * + * @param pos the position of the frame in the <code>info</code> + * field of <code>attribute_info</code> structure. + * @param nth the frame is the N-th + * (0, 1st, 2nd, 3rd, 4th, ...) entry. + * @return the position of the next frame. */ - public int typeTag; + int stackMapFrames(int pos, int nth) throws BadBytecode { + int type = info[pos] & 0xff; + if (type < 64) { + sameFrame(pos, type); + pos++; + } + else if (type < 128) + pos = sameLocals(pos, type); + else if (type < 247) + throw new BadBytecode("bad frame_type in StackMapTable"); + else if (type == 247) // SAME_LOCALS_1_STACK_ITEM_EXTENDED + pos = sameLocals(pos, type); + else if (type < 251) { + int offset = ByteArray.readU16bit(info, pos + 1); + chopFrame(pos, offset, 251 - type); + pos += 3; + } + else if (type == 251) { // SAME_FRAME_EXTENDED + int offset = ByteArray.readU16bit(info, pos + 1); + sameFrame(pos, offset); + pos += 3; + } + else if (type < 255) + pos = appendFrame(pos, type); + else // FULL_FRAME + pos = fullFrame(pos); + + return pos; + } /** - * <code>stack[0].cpool_index</code> or <code>stack[0].offset</code>. + * Invoked if the visited frame is a <code>same_frame</code> or + * a <code>same_frame_extended</code>. + * + * @param pos the position of this frame in the <code>info</code> + * field of <code>attribute_info</code> structure. + * @param offsetDelta */ - public int typeValue; - } + public void sameFrame(int pos, int offsetDelta) {} + + private int sameLocals(int pos, int type) { + int offset; + if (type < 128) + offset = type - 64; + else { // type == 247 + offset = ByteArray.readU16bit(info, pos + 1); + pos += 2; + } + + int tag = info[pos + 1] & 0xff; + int data = 0; + if (tag == OBJECT || tag == UNINIT) { + data = ByteArray.readU16bit(info, pos + 2); + pos += 2; + } + + sameLocals(pos, offset, tag, data); + return pos + 2; + } - /** - * <code>chop_frame</code>. - */ - public static class ChopFrame extends StackMapFrame { /** - * The minimum value of <code>CHOP</code>. + * Invoked if the visited frame is a <code>same_locals_1_stack_item_frame</code> + * or a <code>same_locals_1_stack_item_frame_extended</code>. + * + * @param pos the position. + * @param offsetDelta + * @param stackTag <code>stack[0].tag</code>. + * @param stackData <code>stack[0].cpool_index</code> + * if the tag is <code>OBJECT</code>, + * or <code>stack[0].offset</code> + * if the tag is <code>UNINIT</code>. */ - public static final int FRAME_TYPE = 248; + public void sameLocals(int pos, int offsetDelta, int stackTag, int stackData) {} /** - * The maximum value of <code>CHOP</code>. + * Invoked if the visited frame is a <code>chop_frame</code>. + * + * @param pos the position. + * @param offsetDelta + * @param k the <cod>k</code> last locals are absent. */ - public static final int FRAME_TYPE_MAX = 250; + public void chopFrame(int pos, int offsetDelta, int k) {} + + private int appendFrame(int pos, int type) { + int k = type - 251; + int offset = ByteArray.readU16bit(info, pos + 1); + int[] tags = new int[k]; + int[] data = new int[k]; + int p = pos + 3; + for (int i = 0; i < k; i++) { + int tag = info[p] & 0xff; + tags[i] = tag; + if (tag == OBJECT || tag == UNINIT) { + data[i] = ByteArray.readU16bit(info, p + 1); + p += 3; + } + else { + data[i] = 0; + p++; + } + } + + appendFrame(pos, offset, tags, data); + return p; + } /** - * <code>u1 frame_type</code>. + * Invoked if the visited frame is a <code>append_frame</code>. + * + * @param pos the position. + * @param offsetDelta + * @param tags <code>locals[i].tag</code>. + * @param data <code>locals[i].cpool_index</code> + * or <cod>locals[i].offset</code>. */ - public int frameType; - } + public void appendFrame(int pos, int offsetDelta, int[] tags, int[] data) {} + + private int fullFrame(int pos) { + int offset = ByteArray.readU16bit(info, pos + 1); + int numOfLocals = ByteArray.readU16bit(info, pos + 3); + int[] localsTags = new int[numOfLocals]; + int[] localsData = new int[numOfLocals]; + int p = verifyTypeInfo(pos + 5, numOfLocals, localsTags, localsData); + int numOfItems = ByteArray.readU16bit(info, p); + int[] itemsTags = new int[numOfItems]; + int[] itemsData = new int[numOfItems]; + p = verifyTypeInfo(p + 2, numOfItems, itemsTags, itemsData); + fullFrame(pos, offset, localsTags, localsData, itemsTags, itemsData); + return p; + } - /** - * <code>same_frame_extended</code>. - */ - public static class SameFrameExtended extends StackMapFrame { /** - * <code>SAME_FRAME_EXTENDED</code>. + * Invoked if the visited frame is <code>full_frame</code>. + * + * @param pos the position. + * @param offsetDelta + * @param localTags <code>locals[i].tag</code> + * @param localData <code>locals[i].cpool_index</code> + * or <code>locals[i].offset</code> + * @param stackTags <code>stack[i].tag</code> + * @param stackData <code>stack[i].cpool_index</code> + * or <code>stack[i].offset</code> */ - public static final int FRAME_TYPE = 251; + void fullFrame(int pos, int offsetDelta, int[] localTags, int[] localData, + int[] stackTags, int[] stackData) {} + + private int verifyTypeInfo(int pos, int n, int[] tags, int[] data) { + for (int i = 0; i < n; i++) { + int tag = info[pos++] & 0xff; + tags[i] = tag; + if (tag == OBJECT || tag == UNINIT) { + data[i] = ByteArray.readU16bit(info, pos); + pos += 2; + } + } + + return pos; + } } /** - * <code>append_frame</code>. + * A writer of stack map tables. */ - public static class AppendFrame extends StackMapFrame { - /** - * The minimum value of <code>APPEND</code>. - */ - public static final int FRAME_TYPE = 252; + static class Writer { + ByteArrayOutputStream output; + int numOfEntries; /** - * The maximum value of <code>APPEND</code>. + * Constructs a writer. + * @param size the initial buffer size. */ - public static final int FRAME_TYPE_MAX = 254; + public Writer(int size) { + output = new ByteArrayOutputStream(size); + numOfEntries = 0; + output.write(0); // u2 number_of_entries + output.write(0); + } /** - * <code>u1 frame_type</code>. + * Returns the stack map table written out. */ - public int frameType; + public byte[] toByteArray() { + byte[] b = output.toByteArray(); + ByteArray.write16bit(numOfEntries, b, 0); + return b; + } /** - * <code>locals[?].tag</code>. - * <code>typeTags.length</code> and <code>typeValues.length</code> - * are equal to <code>number_of_locals</code>. + * Writes a <code>same_frame</code> or a <code>same_frame_extended</code>. */ - public int[] typeTags; + public void sameFrame(int offsetDelta) { + numOfEntries++; + if (offsetDelta < 64) + output.write(offsetDelta); + else { + output.write(251); // SAME_FRAME_EXTENDED + write16(offsetDelta); + } + } /** - * <code>locals[?].cpool_index</code> or <code>locals[?].offset</code>. - * <code>typeTags.length</code> and <code>typeValues.length</code> - * are equal to <code>number_of_locals</code>. + * Writes a <code>same_locals_1_stack_item</code> + * or a <code>same_locals_1_stack_item_extended</code>. + * + * @param tag <code>stack[0].tag</code>. + * @param data <code>stack[0].cpool_index</code> + * if the tag is <code>OBJECT</code>, + * or <cod>stack[0].offset</code> + * if the tag is <code>UNINIT</code>. + * Otherwise, this parameter is not used. */ - public int[] typeValues; - } + public void sameLocals(int offsetDelta, int tag, int data) { + numOfEntries++; + if (offsetDelta < 64) + output.write(offsetDelta + 64); + else { + output.write(247); // SAME_LOCALS_1_STACK_ITEM_EXTENDED + write16(offsetDelta); + } + + writeTypeInfo(tag, data); + } - /** - * <code>ful_frame</code>. - */ - public static class FullFrame extends StackMapFrame { /** - * <code>FULL_FRAME</code>. + * Writes a <code>chop_frame</code>. + * + * @param k the number of absent locals. 1, 2, or 3. */ - public static final int FRAME_TYPE = 255; + public void chopFrame(int offsetDelta, int k) { + numOfEntries++; + output.write(251 - k); + write16(offsetDelta); + } /** - * <code>locals[?].tag</code>. - * <code>typeTags.length</code> and <code>typeValues.length</code> - * are equal to <code>number_of_locals</code>. + * Writes a <code>append_frame</code>. + * + * @param tag <code>locals[].tag</code>. + * The length of this array must be + * either 1, 2, or 3. + * @param data <code>locals[].cpool_index</code> + * if the tag is <code>OBJECT</code>, + * or <cod>locals[].offset</code> + * if the tag is <code>UNINIT</code>. + * Otherwise, this parameter is not used. */ - public int[] typeTags; + public void appendFrame(int offsetDelta, int[] tags, int[] data) { + numOfEntries++; + int k = tags.length; // k is 1, 2, or 3 + output.write(k + 251); + write16(offsetDelta); + for (int i = 0; i < k; i++) + writeTypeInfo(tags[i], data[i]); + } /** - * <code>locals[?].cpool_index</code> or <code>locals[?].offset</code>. - * <code>typeTags.length</code> and <code>typeValues.length</code> - * are equal to <code>number_of_locals</code>. + * Writes a <code>full_frame</code>. + * + * @param localTags <code>locals[].tag</code>. + * @param localData <code>locals[].cpool_index</code> + * if the tag is <code>OBJECT</code>, + * or <cod>locals[].offset</code> + * if the tag is <code>UNINIT</code>. + * Otherwise, this parameter is not used. + * @param stackTags <code>stack[].tag</code>. + * @param stackData <code>stack[].cpool_index</code> + * if the tag is <code>OBJECT</code>, + * or <cod>stack[].offset</code> + * if the tag is <code>UNINIT</code>. + * Otherwise, this parameter is not used. */ - public int[] typeValues; + public void fullFrame(int offsetDelta, int[] localTags, int[] localData, + int[] stackTags, int[] stackData) { + numOfEntries++; + output.write(255); // FULL_FRAME + write16(offsetDelta); + int n = localTags.length; + write16(n); + for (int i = 0; i < n; i++) + writeTypeInfo(localTags[i], localData[i]); + + n = stackTags.length; + for (int i = 0; i < n; i++) + writeTypeInfo(stackTags[i], stackData[i]); + } - /** - * <code>stack[?].tag</code>. - * <code>stackTypeTags.length</code> and <code>stackTypeValues.length</code> - * are equal to <code>number_of_stack_items</code>. - */ - public int[] stackTypeTags; + private void writeTypeInfo(int tag, int data) { + output.write(tag); + if (tag == OBJECT || tag == UNINIT) + write16(data); + } - /** - * <code>stack[?].cpool_index</code> or <code>locals[?].offset</code>. - * <code>stackTypeTags.length</code> and <code>stackTypeValues.length</code> - * are equal to <code>number_of_stack_items</code>. - */ - public int[] stackTypeValues; + private void write16(int value) { + output.write((value >>> 8) & 0xff); + output.write(value & 0xff); + } } } |