aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Readme.html2
-rw-r--r--build.xml2
-rw-r--r--src/main/META-INF/MANIFEST.MF2
-rw-r--r--src/main/javassist/ClassPool.java2
-rw-r--r--src/main/javassist/bytecode/StackMapTable.java424
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>.
diff --git a/build.xml b/build.xml
index 00973528..a3dcadaf 100644
--- a/build.xml
+++ b/build.xml
@@ -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);
+ }
}
}