[jboss-cvs] JBossAS SVN: r105871 - projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/util/objectweb/asm.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Wed Jun 9 10:05:41 EDT 2010
Author: kabir.khan at jboss.com
Date: 2010-06-09 10:05:40 -0400 (Wed, 09 Jun 2010)
New Revision: 105871
Modified:
projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/util/objectweb/asm/ClassReader.java
Log:
[JBREFLECT-125] Reformat, since I'm going to make some changes to this class
Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/util/objectweb/asm/ClassReader.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/util/objectweb/asm/ClassReader.java 2010-06-09 14:03:57 UTC (rev 105870)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/util/objectweb/asm/ClassReader.java 2010-06-09 14:05:40 UTC (rev 105871)
@@ -41,1980 +41,2102 @@
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
-public class ClassReader {
+public class ClassReader
+{
- /**
- * True to enable signatures support.
- */
- static final boolean SIGNATURES = true;
-
- /**
- * True to enable annotations support.
- */
- static final boolean ANNOTATIONS = true;
-
- /**
- * True to enable stack map frames support.
- */
- static final boolean FRAMES = true;
-
- /**
- * True to enable bytecode writing support.
- */
- static final boolean WRITER = true;
-
- /**
- * True to enable JSR_W and GOTO_W support.
- */
- static final boolean RESIZE = true;
-
- /**
- * Flag to skip method code. If this class is set <code>CODE</code>
- * attribute won't be visited. This can be used, for example, to retrieve
- * annotations for methods and method parameters.
- */
- public static final int SKIP_CODE = 1;
+ /**
+ * True to enable signatures support.
+ */
+ static final boolean SIGNATURES = true;
- /**
- * Flag to skip the debug information in the class. If this flag is set the
- * debug information of the class is not visited, i.e. the
- * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
- * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
- * called.
- */
- public static final int SKIP_DEBUG = 2;
+ /**
+ * True to enable annotations support.
+ */
+ static final boolean ANNOTATIONS = true;
- /**
- * Flag to skip the stack map frames in the class. If this flag is set the
- * stack map frames of the class is not visited, i.e. the
- * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
- * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
- * used: it avoids visiting frames that will be ignored and recomputed from
- * scratch in the class writer.
- */
- public static final int SKIP_FRAMES = 4;
+ /**
+ * True to enable stack map frames support.
+ */
+ static final boolean FRAMES = true;
- /**
- * Flag to expand the stack map frames. By default stack map frames are
- * visited in their original format (i.e. "expanded" for classes whose
- * version is less than V1_6, and "compressed" for the other classes). If
- * this flag is set, stack map frames are always visited in expanded format
- * (this option adds a decompression/recompression step in ClassReader and
- * ClassWriter which degrades performances quite a lot).
- */
- public static final int EXPAND_FRAMES = 8;
+ /**
+ * True to enable bytecode writing support.
+ */
+ static final boolean WRITER = true;
- /**
- * The class to be parsed. <i>The content of this array must not be
- * modified. This field is intended for {@link Attribute} sub classes, and
- * is normally not needed by class generators or adapters.</i>
- */
- public final byte[] b;
+ /**
+ * True to enable JSR_W and GOTO_W support.
+ */
+ static final boolean RESIZE = true;
- /**
- * The start index of each constant pool item in {@link #b b}, plus one.
- * The one byte offset skips the constant pool item tag that indicates its
- * type.
- */
- private final int[] items;
+ /**
+ * Flag to skip method code. If this class is set <code>CODE</code>
+ * attribute won't be visited. This can be used, for example, to retrieve
+ * annotations for methods and method parameters.
+ */
+ public static final int SKIP_CODE = 1;
- /**
- * The String objects corresponding to the CONSTANT_Utf8 items. This cache
- * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
- * which GREATLY improves performances (by a factor 2 to 3). This caching
- * strategy could be extended to all constant pool items, but its benefit
- * would not be so great for these items (because they are much less
- * expensive to parse than CONSTANT_Utf8 items).
- */
- private final String[] strings;
+ /**
+ * Flag to skip the debug information in the class. If this flag is set the
+ * debug information of the class is not visited, i.e. the
+ * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
+ * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
+ * called.
+ */
+ public static final int SKIP_DEBUG = 2;
- /**
- * Maximum length of the strings contained in the constant pool of the
- * class.
- */
- private final int maxStringLength;
+ /**
+ * Flag to skip the stack map frames in the class. If this flag is set the
+ * stack map frames of the class is not visited, i.e. the
+ * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
+ * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
+ * used: it avoids visiting frames that will be ignored and recomputed from
+ * scratch in the class writer.
+ */
+ public static final int SKIP_FRAMES = 4;
- /**
- * Start index of the class header information (access, name...) in
- * {@link #b b}.
- */
- public final int header;
+ /**
+ * Flag to expand the stack map frames. By default stack map frames are
+ * visited in their original format (i.e. "expanded" for classes whose
+ * version is less than V1_6, and "compressed" for the other classes). If
+ * this flag is set, stack map frames are always visited in expanded format
+ * (this option adds a decompression/recompression step in ClassReader and
+ * ClassWriter which degrades performances quite a lot).
+ */
+ public static final int EXPAND_FRAMES = 8;
- // ------------------------------------------------------------------------
- // Constructors
- // ------------------------------------------------------------------------
+ /**
+ * The class to be parsed. <i>The content of this array must not be
+ * modified. This field is intended for {@link Attribute} sub classes, and
+ * is normally not needed by class generators or adapters.</i>
+ */
+ public final byte[] b;
- /**
- * Constructs a new {@link ClassReader} object.
- *
- * @param b the bytecode of the class to be read.
- */
- public ClassReader(final byte[] b) {
- this(b, 0, b.length);
- }
+ /**
+ * The start index of each constant pool item in {@link #b b}, plus one.
+ * The one byte offset skips the constant pool item tag that indicates its
+ * type.
+ */
+ private final int[] items;
- /**
- * Constructs a new {@link ClassReader} object.
- *
- * @param b the bytecode of the class to be read.
- * @param off the start offset of the class data.
- * @param len the length of the class data.
- */
- public ClassReader(final byte[] b, final int off, final int len) {
- this.b = b;
- // parses the constant pool
- items = new int[readUnsignedShort(off + 8)];
- int n = items.length;
- strings = new String[n];
- int max = 0;
- int index = off + 10;
- for (int i = 1; i < n; ++i) {
- items[i] = index + 1;
- int size;
- switch (b[index]) {
- case ClassWriter.FIELD:
- case ClassWriter.METH:
- case ClassWriter.IMETH:
- case ClassWriter.INT:
- case ClassWriter.FLOAT:
- case ClassWriter.NAME_TYPE:
- size = 5;
- break;
- case ClassWriter.LONG:
- case ClassWriter.DOUBLE:
- size = 9;
- ++i;
- break;
- case ClassWriter.UTF8:
- size = 3 + readUnsignedShort(index + 1);
- if (size > max) {
- max = size;
- }
- break;
- // case ClassWriter.CLASS:
- // case ClassWriter.STR:
- default:
- size = 3;
- break;
- }
- index += size;
- }
- maxStringLength = max;
- // the class header information starts just after the constant pool
- header = index;
- }
+ /**
+ * The String objects corresponding to the CONSTANT_Utf8 items. This cache
+ * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
+ * which GREATLY improves performances (by a factor 2 to 3). This caching
+ * strategy could be extended to all constant pool items, but its benefit
+ * would not be so great for these items (because they are much less
+ * expensive to parse than CONSTANT_Utf8 items).
+ */
+ private final String[] strings;
- /**
- * Returns the class's access flags (see {@link Opcodes}). This value may
- * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
- * and those flags are represented by attributes.
- *
- * @return the class access flags
- *
- * @see ClassVisitor#visit(int, int, String, String, String, String[])
- */
- public int getAccess() {
- return readUnsignedShort(header);
- }
+ /**
+ * Maximum length of the strings contained in the constant pool of the
+ * class.
+ */
+ private final int maxStringLength;
- /**
- * Returns the internal name of the class (see
- * {@link Type#getInternalName() getInternalName}).
- *
- * @return the internal class name
- *
- * @see ClassVisitor#visit(int, int, String, String, String, String[])
- */
- public String getClassName() {
- return readClass(header + 2, new char[maxStringLength]);
- }
+ /**
+ * Start index of the class header information (access, name...) in
+ * {@link #b b}.
+ */
+ public final int header;
- /**
- * Returns the internal of name of the super class (see
- * {@link Type#getInternalName() getInternalName}). For interfaces, the
- * super class is {@link Object}.
- *
- * @return the internal name of super class, or <tt>null</tt> for
- * {@link Object} class.
- *
- * @see ClassVisitor#visit(int, int, String, String, String, String[])
- */
- public String getSuperName() {
- int n = items[readUnsignedShort(header + 4)];
- return n == 0 ? null : readUTF8(n, new char[maxStringLength]);
- }
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
- /**
- * Returns the internal names of the class's interfaces (see
- * {@link Type#getInternalName() getInternalName}).
- *
- * @return the array of internal names for all implemented interfaces or
- * <tt>null</tt>.
- *
- * @see ClassVisitor#visit(int, int, String, String, String, String[])
- */
- public String[] getInterfaces() {
- int index = header + 6;
- int n = readUnsignedShort(index);
- String[] interfaces = new String[n];
- if (n > 0) {
- char[] buf = new char[maxStringLength];
- for (int i = 0; i < n; ++i) {
- index += 2;
- interfaces[i] = readClass(index, buf);
- }
- }
- return interfaces;
- }
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param b the bytecode of the class to be read.
+ */
+ public ClassReader(final byte[] b)
+ {
+ this(b, 0, b.length);
+ }
- /**
- * Copies the constant pool data into the given {@link ClassWriter}. Should
- * be called before the {@link #accept(ClassVisitor,int)} method.
- *
- * @param classWriter the {@link ClassWriter} to copy constant pool into.
- */
- void copyPool(final ClassWriter classWriter) {
- char[] buf = new char[maxStringLength];
- int ll = items.length;
- Item[] items2 = new Item[ll];
- for (int i = 1; i < ll; i++) {
- int index = items[i];
- int tag = b[index - 1];
- Item item = new Item(i);
- int nameType;
- switch (tag) {
- case ClassWriter.FIELD:
- case ClassWriter.METH:
- case ClassWriter.IMETH:
- nameType = items[readUnsignedShort(index + 2)];
- item.set(tag,
- readClass(index, buf),
- readUTF8(nameType, buf),
- readUTF8(nameType + 2, buf));
- break;
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param b the bytecode of the class to be read.
+ * @param off the start offset of the class data.
+ * @param len the length of the class data.
+ */
+ public ClassReader(final byte[] b, final int off, final int len)
+ {
+ this.b = b;
+ // parses the constant pool
+ items = new int[readUnsignedShort(off + 8)];
+ int n = items.length;
+ strings = new String[n];
+ int max = 0;
+ int index = off + 10;
+ for (int i = 1; i < n; ++i)
+ {
+ items[i] = index + 1;
+ int size;
+ switch (b[index])
+ {
+ case ClassWriter.FIELD :
+ case ClassWriter.METH :
+ case ClassWriter.IMETH :
+ case ClassWriter.INT :
+ case ClassWriter.FLOAT :
+ case ClassWriter.NAME_TYPE :
+ size = 5;
+ break;
+ case ClassWriter.LONG :
+ case ClassWriter.DOUBLE :
+ size = 9;
+ ++i;
+ break;
+ case ClassWriter.UTF8 :
+ size = 3 + readUnsignedShort(index + 1);
+ if (size > max)
+ {
+ max = size;
+ }
+ break;
+ // case ClassWriter.CLASS:
+ // case ClassWriter.STR:
+ default :
+ size = 3;
+ break;
+ }
+ index += size;
+ }
+ maxStringLength = max;
+ // the class header information starts just after the constant pool
+ header = index;
+ }
- case ClassWriter.INT:
- item.set(readInt(index));
- break;
+ /**
+ * Returns the class's access flags (see {@link Opcodes}). This value may
+ * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
+ * and those flags are represented by attributes.
+ *
+ * @return the class access flags
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public int getAccess()
+ {
+ return readUnsignedShort(header);
+ }
- case ClassWriter.FLOAT:
- item.set(Float.intBitsToFloat(readInt(index)));
- break;
+ /**
+ * Returns the internal name of the class (see
+ * {@link Type#getInternalName() getInternalName}).
+ *
+ * @return the internal class name
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String getClassName()
+ {
+ return readClass(header + 2, new char[maxStringLength]);
+ }
- case ClassWriter.NAME_TYPE:
- item.set(tag,
- readUTF8(index, buf),
- readUTF8(index + 2, buf),
- null);
- break;
+ /**
+ * Returns the internal of name of the super class (see
+ * {@link Type#getInternalName() getInternalName}). For interfaces, the
+ * super class is {@link Object}.
+ *
+ * @return the internal name of super class, or <tt>null</tt> for
+ * {@link Object} class.
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String getSuperName()
+ {
+ int n = items[readUnsignedShort(header + 4)];
+ return n == 0 ? null : readUTF8(n, new char[maxStringLength]);
+ }
- case ClassWriter.LONG:
- item.set(readLong(index));
- ++i;
- break;
+ /**
+ * Returns the internal names of the class's interfaces (see
+ * {@link Type#getInternalName() getInternalName}).
+ *
+ * @return the array of internal names for all implemented interfaces or
+ * <tt>null</tt>.
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String[] getInterfaces()
+ {
+ int index = header + 6;
+ int n = readUnsignedShort(index);
+ String[] interfaces = new String[n];
+ if (n > 0)
+ {
+ char[] buf = new char[maxStringLength];
+ for (int i = 0; i < n; ++i)
+ {
+ index += 2;
+ interfaces[i] = readClass(index, buf);
+ }
+ }
+ return interfaces;
+ }
- case ClassWriter.DOUBLE:
- item.set(Double.longBitsToDouble(readLong(index)));
- ++i;
- break;
+ /**
+ * Copies the constant pool data into the given {@link ClassWriter}. Should
+ * be called before the {@link #accept(ClassVisitor,int)} method.
+ *
+ * @param classWriter the {@link ClassWriter} to copy constant pool into.
+ */
+ void copyPool(final ClassWriter classWriter)
+ {
+ char[] buf = new char[maxStringLength];
+ int ll = items.length;
+ Item[] items2 = new Item[ll];
+ for (int i = 1; i < ll; i++)
+ {
+ int index = items[i];
+ int tag = b[index - 1];
+ Item item = new Item(i);
+ int nameType;
+ switch (tag)
+ {
+ case ClassWriter.FIELD :
+ case ClassWriter.METH :
+ case ClassWriter.IMETH :
+ nameType = items[readUnsignedShort(index + 2)];
+ item.set(tag, readClass(index, buf), readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
+ break;
- case ClassWriter.UTF8: {
- String s = strings[i];
- if (s == null) {
- index = items[i];
- s = strings[i] = readUTF(index + 2,
- readUnsignedShort(index),
- buf);
- }
- item.set(tag, s, null, null);
- }
- break;
+ case ClassWriter.INT :
+ item.set(readInt(index));
+ break;
- // case ClassWriter.STR:
- // case ClassWriter.CLASS:
- default:
- item.set(tag, readUTF8(index, buf), null, null);
- break;
+ case ClassWriter.FLOAT :
+ item.set(Float.intBitsToFloat(readInt(index)));
+ break;
+
+ case ClassWriter.NAME_TYPE :
+ item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf), null);
+ break;
+
+ case ClassWriter.LONG :
+ item.set(readLong(index));
+ ++i;
+ break;
+
+ case ClassWriter.DOUBLE :
+ item.set(Double.longBitsToDouble(readLong(index)));
+ ++i;
+ break;
+
+ case ClassWriter.UTF8 : {
+ String s = strings[i];
+ if (s == null)
+ {
+ index = items[i];
+ s = strings[i] = readUTF(index + 2, readUnsignedShort(index), buf);
+ }
+ item.set(tag, s, null, null);
}
+ break;
- int index2 = item.hashCode % items2.length;
- item.next = items2[index2];
- items2[index2] = item;
- }
+ // case ClassWriter.STR:
+ // case ClassWriter.CLASS:
+ default :
+ item.set(tag, readUTF8(index, buf), null, null);
+ break;
+ }
- int off = items[1] - 1;
- classWriter.pool.putByteArray(b, off, header - off);
- classWriter.items = items2;
- classWriter.threshold = (int) (0.75d * ll);
- classWriter.index = ll;
- }
+ int index2 = item.hashCode % items2.length;
+ item.next = items2[index2];
+ items2[index2] = item;
+ }
- /**
- * Constructs a new {@link ClassReader} object.
- *
- * @param is an input stream from which to read the class.
- * @throws IOException if a problem occurs during reading.
- */
- public ClassReader(final InputStream is) throws IOException {
- this(readClass(is));
- }
+ int off = items[1] - 1;
+ classWriter.pool.putByteArray(b, off, header - off);
+ classWriter.items = items2;
+ classWriter.threshold = (int) (0.75d * ll);
+ classWriter.index = ll;
+ }
- /**
- * Constructs a new {@link ClassReader} object.
- *
- * @param name the fully qualified name of the class to be read.
- * @throws IOException if an exception occurs during reading.
- */
- public ClassReader(final String name) throws IOException {
- this(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
- + ".class"));
- }
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param is an input stream from which to read the class.
+ * @throws IOException if a problem occurs during reading.
+ */
+ public ClassReader(final InputStream is) throws IOException
+ {
+ this(readClass(is));
+ }
- /**
- * Reads the bytecode of a class.
- *
- * @param is an input stream from which to read the class.
- * @return the bytecode read from the given input stream.
- * @throws IOException if a problem occurs during reading.
- */
- private static byte[] readClass(final InputStream is) throws IOException {
- if (is == null) {
- throw new IOException("Class not found");
- }
- byte[] b = new byte[is.available()];
- int len = 0;
- while (true) {
- int n = is.read(b, len, b.length - len);
- if (n == -1) {
- if (len < b.length) {
- byte[] c = new byte[len];
- System.arraycopy(b, 0, c, 0, len);
- b = c;
- }
- return b;
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param name the fully qualified name of the class to be read.
+ * @throws IOException if an exception occurs during reading.
+ */
+ public ClassReader(final String name) throws IOException
+ {
+ this(ClassLoader.getSystemResourceAsStream(name.replace('.', '/') + ".class"));
+ }
+
+ /**
+ * Reads the bytecode of a class.
+ *
+ * @param is an input stream from which to read the class.
+ * @return the bytecode read from the given input stream.
+ * @throws IOException if a problem occurs during reading.
+ */
+ private static byte[] readClass(final InputStream is) throws IOException
+ {
+ if (is == null)
+ {
+ throw new IOException("Class not found");
+ }
+ byte[] b = new byte[is.available()];
+ int len = 0;
+ while (true)
+ {
+ int n = is.read(b, len, b.length - len);
+ if (n == -1)
+ {
+ if (len < b.length)
+ {
+ byte[] c = new byte[len];
+ System.arraycopy(b, 0, c, 0, len);
+ b = c;
}
- len += n;
- if (len == b.length) {
- int last = is.read();
- if (last < 0) {
- return b;
- }
- byte[] c = new byte[b.length + 1000];
- System.arraycopy(b, 0, c, 0, len);
- c[len++] = (byte) last;
- b = c;
+ return b;
+ }
+ len += n;
+ if (len == b.length)
+ {
+ int last = is.read();
+ if (last < 0)
+ {
+ return b;
}
- }
- }
+ byte[] c = new byte[b.length + 1000];
+ System.arraycopy(b, 0, c, 0, len);
+ c[len++] = (byte) last;
+ b = c;
+ }
+ }
+ }
- // ------------------------------------------------------------------------
- // Public methods
- // ------------------------------------------------------------------------
+ // ------------------------------------------------------------------------
+ // Public methods
+ // ------------------------------------------------------------------------
- /**
- * Makes the given visitor visit the Java class of this {@link ClassReader}.
- * This class is the one specified in the constructor (see
- * {@link #ClassReader(byte[]) ClassReader}).
- *
- * @param classVisitor the visitor that must visit this class.
- * @param flags option flags that can be used to modify the default behavior
- * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
- * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
- */
- public void accept(final ClassVisitor classVisitor, final int flags) {
- accept(classVisitor, new Attribute[0], flags);
- }
+ /**
+ * Makes the given visitor visit the Java class of this {@link ClassReader}.
+ * This class is the one specified in the constructor (see
+ * {@link #ClassReader(byte[]) ClassReader}).
+ *
+ * @param classVisitor the visitor that must visit this class.
+ * @param flags option flags that can be used to modify the default behavior
+ * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
+ * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+ */
+ public void accept(final ClassVisitor classVisitor, final int flags)
+ {
+ accept(classVisitor, new Attribute[0], flags);
+ }
- /**
- * Makes the given visitor visit the Java class of this {@link ClassReader}.
- * This class is the one specified in the constructor (see
- * {@link #ClassReader(byte[]) ClassReader}).
- *
- * @param classVisitor the visitor that must visit this class.
- * @param attrs prototypes of the attributes that must be parsed during the
- * visit of the class. Any attribute whose type is not equal to the
- * type of one the prototypes will not be parsed: its byte array
- * value will be passed unchanged to the ClassWriter. <i>This may
- * corrupt it if this value contains references to the constant pool,
- * or has syntactic or semantic links with a class element that has
- * been transformed by a class adapter between the reader and the
- * writer</i>.
- * @param flags option flags that can be used to modify the default behavior
- * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
- * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
- */
- public void accept(
- final ClassVisitor classVisitor,
- final Attribute[] attrs,
- final int flags)
- {
- byte[] b = this.b; // the bytecode array
- char[] c = new char[maxStringLength]; // buffer used to read strings
- int i, j, k; // loop variables
- int u, v, w; // indexes in b
- Attribute attr;
+ /**
+ * Makes the given visitor visit the Java class of this {@link ClassReader}.
+ * This class is the one specified in the constructor (see
+ * {@link #ClassReader(byte[]) ClassReader}).
+ *
+ * @param classVisitor the visitor that must visit this class.
+ * @param attrs prototypes of the attributes that must be parsed during the
+ * visit of the class. Any attribute whose type is not equal to the
+ * type of one the prototypes will not be parsed: its byte array
+ * value will be passed unchanged to the ClassWriter. <i>This may
+ * corrupt it if this value contains references to the constant pool,
+ * or has syntactic or semantic links with a class element that has
+ * been transformed by a class adapter between the reader and the
+ * writer</i>.
+ * @param flags option flags that can be used to modify the default behavior
+ * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
+ * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+ */
+ public void accept(final ClassVisitor classVisitor, final Attribute[] attrs, final int flags)
+ {
+ byte[] b = this.b; // the bytecode array
+ char[] c = new char[maxStringLength]; // buffer used to read strings
+ int i, j, k; // loop variables
+ int u, v, w; // indexes in b
+ Attribute attr;
- int access;
- String name;
- String desc;
- String attrName;
- String signature;
- int anns = 0;
- int ianns = 0;
- Attribute cattrs = null;
+ int access;
+ String name;
+ String desc;
+ String attrName;
+ String signature;
+ int anns = 0;
+ int ianns = 0;
+ Attribute cattrs = null;
- // visits the header
- u = header;
- access = readUnsignedShort(u);
- name = readClass(u + 2, c);
- v = items[readUnsignedShort(u + 4)];
- String superClassName = v == 0 ? null : readUTF8(v, c);
- String[] implementedItfs = new String[readUnsignedShort(u + 6)];
- w = 0;
- u += 8;
- for (i = 0; i < implementedItfs.length; ++i) {
- implementedItfs[i] = readClass(u, c);
- u += 2;
- }
+ // visits the header
+ u = header;
+ access = readUnsignedShort(u);
+ name = readClass(u + 2, c);
+ v = items[readUnsignedShort(u + 4)];
+ String superClassName = v == 0 ? null : readUTF8(v, c);
+ String[] implementedItfs = new String[readUnsignedShort(u + 6)];
+ w = 0;
+ u += 8;
+ for (i = 0; i < implementedItfs.length; ++i)
+ {
+ implementedItfs[i] = readClass(u, c);
+ u += 2;
+ }
- boolean skipCode = (flags & SKIP_CODE) != 0;
- boolean skipDebug = (flags & SKIP_DEBUG) != 0;
- boolean unzip = (flags & EXPAND_FRAMES) != 0;
+ boolean skipCode = (flags & SKIP_CODE) != 0;
+ boolean skipDebug = (flags & SKIP_DEBUG) != 0;
+ boolean unzip = (flags & EXPAND_FRAMES) != 0;
- // skips fields and methods
- v = u;
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- j = readUnsignedShort(v + 6);
- v += 8;
- for (; j > 0; --j) {
- v += 6 + readInt(v + 2);
+ // skips fields and methods
+ v = u;
+ i = readUnsignedShort(v);
+ v += 2;
+ for (; i > 0; --i)
+ {
+ j = readUnsignedShort(v + 6);
+ v += 8;
+ for (; j > 0; --j)
+ {
+ v += 6 + readInt(v + 2);
+ }
+ }
+ i = readUnsignedShort(v);
+ v += 2;
+ for (; i > 0; --i)
+ {
+ j = readUnsignedShort(v + 6);
+ v += 8;
+ for (; j > 0; --j)
+ {
+ v += 6 + readInt(v + 2);
+ }
+ }
+ // reads the class's attributes
+ signature = null;
+ String sourceFile = null;
+ String sourceDebug = null;
+ String enclosingOwner = null;
+ String enclosingName = null;
+ String enclosingDesc = null;
+
+ i = readUnsignedShort(v);
+ v += 2;
+ for (; i > 0; --i)
+ {
+ attrName = readUTF8(v, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("SourceFile".equals(attrName))
+ {
+ sourceFile = readUTF8(v + 6, c);
+ }
+ else if ("InnerClasses".equals(attrName))
+ {
+ w = v + 6;
+ }
+ else if ("EnclosingMethod".equals(attrName))
+ {
+ enclosingOwner = readClass(v + 6, c);
+ int item = readUnsignedShort(v + 8);
+ if (item != 0)
+ {
+ enclosingName = readUTF8(items[item], c);
+ enclosingDesc = readUTF8(items[item] + 2, c);
}
- }
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- j = readUnsignedShort(v + 6);
- v += 8;
- for (; j > 0; --j) {
- v += 6 + readInt(v + 2);
+ }
+ else if (SIGNATURES && "Signature".equals(attrName))
+ {
+ signature = readUTF8(v + 6, c);
+ }
+ else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName))
+ {
+ anns = v + 6;
+ }
+ else if ("Deprecated".equals(attrName))
+ {
+ access |= Opcodes.ACC_DEPRECATED;
+ }
+ else if ("Synthetic".equals(attrName))
+ {
+ access |= Opcodes.ACC_SYNTHETIC;
+ }
+ else if ("SourceDebugExtension".equals(attrName))
+ {
+ int len = readInt(v + 2);
+ sourceDebug = readUTF(v + 6, len, new char[len]);
+ }
+ else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName))
+ {
+ ianns = v + 6;
+ }
+ else
+ {
+ attr = readAttribute(attrs, attrName, v + 6, readInt(v + 2), c, -1, null);
+ if (attr != null)
+ {
+ attr.next = cattrs;
+ cattrs = attr;
}
- }
- // reads the class's attributes
- signature = null;
- String sourceFile = null;
- String sourceDebug = null;
- String enclosingOwner = null;
- String enclosingName = null;
- String enclosingDesc = null;
+ }
+ v += 6 + readInt(v + 2);
+ }
+ // calls the visit method
+ classVisitor.visit(readInt(4), access, name, signature, superClassName, implementedItfs);
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- attrName = readUTF8(v, c);
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("SourceFile".equals(attrName)) {
- sourceFile = readUTF8(v + 6, c);
- } else if ("InnerClasses".equals(attrName)) {
- w = v + 6;
- } else if ("EnclosingMethod".equals(attrName)) {
- enclosingOwner = readClass(v + 6, c);
- int item = readUnsignedShort(v + 8);
- if (item != 0) {
- enclosingName = readUTF8(items[item], c);
- enclosingDesc = readUTF8(items[item] + 2, c);
- }
- } else if (SIGNATURES && "Signature".equals(attrName)) {
- signature = readUTF8(v + 6, c);
- } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
- anns = v + 6;
- } else if ("Deprecated".equals(attrName)) {
- access |= Opcodes.ACC_DEPRECATED;
- } else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC;
- } else if ("SourceDebugExtension".equals(attrName)) {
- int len = readInt(v + 2);
- sourceDebug = readUTF(v + 6, len, new char[len]);
- } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = v + 6;
- } else {
- attr = readAttribute(attrs,
- attrName,
- v + 6,
- readInt(v + 2),
- c,
- -1,
- null);
- if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
- }
- }
- v += 6 + readInt(v + 2);
- }
- // calls the visit method
- classVisitor.visit(readInt(4),
- access,
- name,
- signature,
- superClassName,
- implementedItfs);
+ // calls the visitSource method
+ if (!skipDebug && (sourceFile != null || sourceDebug != null))
+ {
+ classVisitor.visitSource(sourceFile, sourceDebug);
+ }
- // calls the visitSource method
- if (!skipDebug && (sourceFile != null || sourceDebug != null)) {
- classVisitor.visitSource(sourceFile, sourceDebug);
- }
+ // calls the visitOuterClass method
+ if (enclosingOwner != null)
+ {
+ classVisitor.visitOuterClass(enclosingOwner, enclosingName, enclosingDesc);
+ }
- // calls the visitOuterClass method
- if (enclosingOwner != null) {
- classVisitor.visitOuterClass(enclosingOwner,
- enclosingName,
- enclosingDesc);
- }
-
- // visits the class annotations
- if (ANNOTATIONS) {
- for (i = 1; i >= 0; --i) {
- v = i == 0 ? ianns : anns;
- if (v != 0) {
- j = readUnsignedShort(v);
- v += 2;
- for (; j > 0; --j) {
- v = readAnnotationValues(v + 2,
- c,
- true,
- classVisitor.visitAnnotation(readUTF8(v, c), i != 0));
- }
- }
+ // visits the class annotations
+ if (ANNOTATIONS)
+ {
+ for (i = 1; i >= 0; --i)
+ {
+ v = i == 0 ? ianns : anns;
+ if (v != 0)
+ {
+ j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j)
+ {
+ v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), i != 0));
+ }
}
- }
+ }
+ }
- // visits the class attributes
- while (cattrs != null) {
- attr = cattrs.next;
- cattrs.next = null;
- classVisitor.visitAttribute(cattrs);
- cattrs = attr;
- }
+ // visits the class attributes
+ while (cattrs != null)
+ {
+ attr = cattrs.next;
+ cattrs.next = null;
+ classVisitor.visitAttribute(cattrs);
+ cattrs = attr;
+ }
- // calls the visitInnerClass method
- if (w != 0) {
- i = readUnsignedShort(w);
- w += 2;
- for (; i > 0; --i) {
- classVisitor.visitInnerClass(readUnsignedShort(w) == 0
+ // calls the visitInnerClass method
+ if (w != 0)
+ {
+ i = readUnsignedShort(w);
+ w += 2;
+ for (; i > 0; --i)
+ {
+ classVisitor.visitInnerClass(readUnsignedShort(w) == 0 ? null : readClass(w, c),
+ readUnsignedShort(w + 2) == 0 ? null : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
? null
- : readClass(w, c), readUnsignedShort(w + 2) == 0
- ? null
- : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
- ? null
: readUTF8(w + 4, c), readUnsignedShort(w + 6));
- w += 8;
- }
- }
+ w += 8;
+ }
+ }
- // visits the fields
- i = readUnsignedShort(u);
- u += 2;
- for (; i > 0; --i) {
- access = readUnsignedShort(u);
- name = readUTF8(u + 2, c);
- desc = readUTF8(u + 4, c);
- // visits the field's attributes and looks for a ConstantValue
- // attribute
- int fieldValueItem = 0;
- signature = null;
- anns = 0;
- ianns = 0;
- cattrs = null;
+ // visits the fields
+ i = readUnsignedShort(u);
+ u += 2;
+ for (; i > 0; --i)
+ {
+ access = readUnsignedShort(u);
+ name = readUTF8(u + 2, c);
+ desc = readUTF8(u + 4, c);
+ // visits the field's attributes and looks for a ConstantValue
+ // attribute
+ int fieldValueItem = 0;
+ signature = null;
+ anns = 0;
+ ianns = 0;
+ cattrs = null;
- j = readUnsignedShort(u + 6);
- u += 8;
- for (; j > 0; --j) {
- attrName = readUTF8(u, c);
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("ConstantValue".equals(attrName)) {
- fieldValueItem = readUnsignedShort(u + 6);
- } else if (SIGNATURES && "Signature".equals(attrName)) {
- signature = readUTF8(u + 6, c);
- } else if ("Deprecated".equals(attrName)) {
- access |= Opcodes.ACC_DEPRECATED;
- } else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC;
- } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
- anns = u + 6;
- } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = u + 6;
- } else {
- attr = readAttribute(attrs,
- attrName,
- u + 6,
- readInt(u + 2),
- c,
- -1,
- null);
- if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
- }
- }
- u += 6 + readInt(u + 2);
+ j = readUnsignedShort(u + 6);
+ u += 8;
+ for (; j > 0; --j)
+ {
+ attrName = readUTF8(u, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("ConstantValue".equals(attrName))
+ {
+ fieldValueItem = readUnsignedShort(u + 6);
}
- // visits the field
- FieldVisitor fv = classVisitor.visitField(access,
- name,
- desc,
- signature,
- fieldValueItem == 0 ? null : readConst(fieldValueItem, c));
- // visits the field annotations and attributes
- if (fv != null) {
- if (ANNOTATIONS) {
- for (j = 1; j >= 0; --j) {
- v = j == 0 ? ianns : anns;
- if (v != 0) {
- k = readUnsignedShort(v);
- v += 2;
- for (; k > 0; --k) {
- v = readAnnotationValues(v + 2,
- c,
- true,
- fv.visitAnnotation(readUTF8(v, c), j != 0));
- }
- }
- }
- }
- while (cattrs != null) {
- attr = cattrs.next;
- cattrs.next = null;
- fv.visitAttribute(cattrs);
- cattrs = attr;
- }
- fv.visitEnd();
+ else if (SIGNATURES && "Signature".equals(attrName))
+ {
+ signature = readUTF8(u + 6, c);
}
- }
+ else if ("Deprecated".equals(attrName))
+ {
+ access |= Opcodes.ACC_DEPRECATED;
+ }
+ else if ("Synthetic".equals(attrName))
+ {
+ access |= Opcodes.ACC_SYNTHETIC;
+ }
+ else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName))
+ {
+ anns = u + 6;
+ }
+ else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName))
+ {
+ ianns = u + 6;
+ }
+ else
+ {
+ attr = readAttribute(attrs, attrName, u + 6, readInt(u + 2), c, -1, null);
+ if (attr != null)
+ {
+ attr.next = cattrs;
+ cattrs = attr;
+ }
+ }
+ u += 6 + readInt(u + 2);
+ }
+ // visits the field
+ FieldVisitor fv = classVisitor.visitField(access, name, desc, signature, fieldValueItem == 0
+ ? null
+ : readConst(fieldValueItem, c));
+ // visits the field annotations and attributes
+ if (fv != null)
+ {
+ if (ANNOTATIONS)
+ {
+ for (j = 1; j >= 0; --j)
+ {
+ v = j == 0 ? ianns : anns;
+ if (v != 0)
+ {
+ k = readUnsignedShort(v);
+ v += 2;
+ for (; k > 0; --k)
+ {
+ v = readAnnotationValues(v + 2, c, true, fv.visitAnnotation(readUTF8(v, c), j != 0));
+ }
+ }
+ }
+ }
+ while (cattrs != null)
+ {
+ attr = cattrs.next;
+ cattrs.next = null;
+ fv.visitAttribute(cattrs);
+ cattrs = attr;
+ }
+ fv.visitEnd();
+ }
+ }
- // visits the methods
- i = readUnsignedShort(u);
- u += 2;
- for (; i > 0; --i) {
- int u0 = u + 6;
- access = readUnsignedShort(u);
- name = readUTF8(u + 2, c);
- desc = readUTF8(u + 4, c);
- signature = null;
- anns = 0;
- ianns = 0;
- int dann = 0;
- int mpanns = 0;
- int impanns = 0;
- cattrs = null;
- v = 0;
- w = 0;
+ // visits the methods
+ i = readUnsignedShort(u);
+ u += 2;
+ for (; i > 0; --i)
+ {
+ int u0 = u + 6;
+ access = readUnsignedShort(u);
+ name = readUTF8(u + 2, c);
+ desc = readUTF8(u + 4, c);
+ signature = null;
+ anns = 0;
+ ianns = 0;
+ int dann = 0;
+ int mpanns = 0;
+ int impanns = 0;
+ cattrs = null;
+ v = 0;
+ w = 0;
- // looks for Code and Exceptions attributes
- j = readUnsignedShort(u + 6);
- u += 8;
- for (; j > 0; --j) {
- attrName = readUTF8(u, c);
- int attrSize = readInt(u + 2);
- u += 6;
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("Code".equals(attrName)) {
- if (!skipCode) {
- v = u;
- }
- } else if ("Exceptions".equals(attrName)) {
- w = u;
- } else if (SIGNATURES && "Signature".equals(attrName)) {
- signature = readUTF8(u, c);
- } else if ("Deprecated".equals(attrName)) {
- access |= Opcodes.ACC_DEPRECATED;
- } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
- anns = u;
- } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
- dann = u;
- } else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC;
- } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = u;
- } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))
- {
- mpanns = u;
- } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))
- {
- impanns = u;
- } else {
- attr = readAttribute(attrs,
- attrName,
- u,
- attrSize,
- c,
- -1,
- null);
- if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
- }
- }
- u += attrSize;
+ // looks for Code and Exceptions attributes
+ j = readUnsignedShort(u + 6);
+ u += 8;
+ for (; j > 0; --j)
+ {
+ attrName = readUTF8(u, c);
+ int attrSize = readInt(u + 2);
+ u += 6;
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("Code".equals(attrName))
+ {
+ if (!skipCode)
+ {
+ v = u;
+ }
}
- // reads declared exceptions
- String[] exceptions;
- if (w == 0) {
- exceptions = null;
- } else {
- exceptions = new String[readUnsignedShort(w)];
- w += 2;
- for (j = 0; j < exceptions.length; ++j) {
- exceptions[j] = readClass(w, c);
- w += 2;
- }
+ else if ("Exceptions".equals(attrName))
+ {
+ w = u;
}
+ else if (SIGNATURES && "Signature".equals(attrName))
+ {
+ signature = readUTF8(u, c);
+ }
+ else if ("Deprecated".equals(attrName))
+ {
+ access |= Opcodes.ACC_DEPRECATED;
+ }
+ else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName))
+ {
+ anns = u;
+ }
+ else if (ANNOTATIONS && "AnnotationDefault".equals(attrName))
+ {
+ dann = u;
+ }
+ else if ("Synthetic".equals(attrName))
+ {
+ access |= Opcodes.ACC_SYNTHETIC;
+ }
+ else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName))
+ {
+ ianns = u;
+ }
+ else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))
+ {
+ mpanns = u;
+ }
+ else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))
+ {
+ impanns = u;
+ }
+ else
+ {
+ attr = readAttribute(attrs, attrName, u, attrSize, c, -1, null);
+ if (attr != null)
+ {
+ attr.next = cattrs;
+ cattrs = attr;
+ }
+ }
+ u += attrSize;
+ }
+ // reads declared exceptions
+ String[] exceptions;
+ if (w == 0)
+ {
+ exceptions = null;
+ }
+ else
+ {
+ exceptions = new String[readUnsignedShort(w)];
+ w += 2;
+ for (j = 0; j < exceptions.length; ++j)
+ {
+ exceptions[j] = readClass(w, c);
+ w += 2;
+ }
+ }
- // visits the method's code, if any
- MethodVisitor mv = classVisitor.visitMethod(access,
- name,
- desc,
- signature,
- exceptions);
+ // visits the method's code, if any
+ MethodVisitor mv = classVisitor.visitMethod(access, name, desc, signature, exceptions);
- if (mv != null) {
- /*
- * if the returned MethodVisitor is in fact a MethodWriter, it
- * means there is no method adapter between the reader and the
- * writer. If, in addition, the writer's constant pool was
- * copied from this reader (mw.cw.cr == this), and the signature
- * and exceptions of the method have not been changed, then it
- * is possible to skip all visit events and just copy the
- * original code of the method to the writer (the access, name
- * and descriptor can have been changed, this is not important
- * since they are not copied as is from the reader).
- */
- if (WRITER && mv instanceof MethodWriter) {
- MethodWriter mw = (MethodWriter) mv;
- if (mw.cw.cr == this) {
- if (signature == mw.signature) {
- boolean sameExceptions = false;
- if (exceptions == null) {
- sameExceptions = mw.exceptionCount == 0;
- } else {
- if (exceptions.length == mw.exceptionCount) {
- sameExceptions = true;
- for (j = exceptions.length - 1; j >= 0; --j)
- {
- w -= 2;
- if (mw.exceptions[j] != readUnsignedShort(w))
- {
- sameExceptions = false;
- break;
- }
- }
- }
- }
- if (sameExceptions) {
- /*
- * we do not copy directly the code into
- * MethodWriter to save a byte array copy
- * operation. The real copy will be done in
- * ClassWriter.toByteArray().
- */
- mw.classReaderOffset = u0;
- mw.classReaderLength = u - u0;
- continue;
- }
+ if (mv != null)
+ {
+ /*
+ * if the returned MethodVisitor is in fact a MethodWriter, it
+ * means there is no method adapter between the reader and the
+ * writer. If, in addition, the writer's constant pool was
+ * copied from this reader (mw.cw.cr == this), and the signature
+ * and exceptions of the method have not been changed, then it
+ * is possible to skip all visit events and just copy the
+ * original code of the method to the writer (the access, name
+ * and descriptor can have been changed, this is not important
+ * since they are not copied as is from the reader).
+ */
+ if (WRITER && mv instanceof MethodWriter)
+ {
+ MethodWriter mw = (MethodWriter) mv;
+ if (mw.cw.cr == this)
+ {
+ if (signature == mw.signature)
+ {
+ boolean sameExceptions = false;
+ if (exceptions == null)
+ {
+ sameExceptions = mw.exceptionCount == 0;
+ }
+ else
+ {
+ if (exceptions.length == mw.exceptionCount)
+ {
+ sameExceptions = true;
+ for (j = exceptions.length - 1; j >= 0; --j)
+ {
+ w -= 2;
+ if (mw.exceptions[j] != readUnsignedShort(w))
+ {
+ sameExceptions = false;
+ break;
+ }
+ }
}
- }
- }
+ }
+ if (sameExceptions)
+ {
+ /*
+ * we do not copy directly the code into
+ * MethodWriter to save a byte array copy
+ * operation. The real copy will be done in
+ * ClassWriter.toByteArray().
+ */
+ mw.classReaderOffset = u0;
+ mw.classReaderLength = u - u0;
+ continue;
+ }
+ }
+ }
+ }
- if (ANNOTATIONS && dann != 0) {
- AnnotationVisitor dv = mv.visitAnnotationDefault();
- readAnnotationValue(dann, c, null, dv);
- if (dv != null) {
- dv.visitEnd();
- }
- }
- if (ANNOTATIONS) {
- for (j = 1; j >= 0; --j) {
- w = j == 0 ? ianns : anns;
- if (w != 0) {
- k = readUnsignedShort(w);
- w += 2;
- for (; k > 0; --k) {
- w = readAnnotationValues(w + 2,
- c,
- true,
- mv.visitAnnotation(readUTF8(w, c), j != 0));
- }
- }
- }
- }
- if (ANNOTATIONS && mpanns != 0) {
- readParameterAnnotations(mpanns, desc, c, true, mv);
- }
- if (ANNOTATIONS && impanns != 0) {
- readParameterAnnotations(impanns, desc, c, false, mv);
- }
- while (cattrs != null) {
- attr = cattrs.next;
- cattrs.next = null;
- mv.visitAttribute(cattrs);
- cattrs = attr;
- }
+ if (ANNOTATIONS && dann != 0)
+ {
+ AnnotationVisitor dv = mv.visitAnnotationDefault();
+ readAnnotationValue(dann, c, null, dv);
+ if (dv != null)
+ {
+ dv.visitEnd();
+ }
}
+ if (ANNOTATIONS)
+ {
+ for (j = 1; j >= 0; --j)
+ {
+ w = j == 0 ? ianns : anns;
+ if (w != 0)
+ {
+ k = readUnsignedShort(w);
+ w += 2;
+ for (; k > 0; --k)
+ {
+ w = readAnnotationValues(w + 2, c, true, mv.visitAnnotation(readUTF8(w, c), j != 0));
+ }
+ }
+ }
+ }
+ if (ANNOTATIONS && mpanns != 0)
+ {
+ readParameterAnnotations(mpanns, desc, c, true, mv);
+ }
+ if (ANNOTATIONS && impanns != 0)
+ {
+ readParameterAnnotations(impanns, desc, c, false, mv);
+ }
+ while (cattrs != null)
+ {
+ attr = cattrs.next;
+ cattrs.next = null;
+ mv.visitAttribute(cattrs);
+ cattrs = attr;
+ }
+ }
- if (mv != null && v != 0) {
- int maxStack = readUnsignedShort(v);
- int maxLocals = readUnsignedShort(v + 2);
- int codeLength = readInt(v + 4);
- v += 8;
+ if (mv != null && v != 0)
+ {
+ int maxStack = readUnsignedShort(v);
+ int maxLocals = readUnsignedShort(v + 2);
+ int codeLength = readInt(v + 4);
+ v += 8;
- int codeStart = v;
- int codeEnd = v + codeLength;
+ int codeStart = v;
+ int codeEnd = v + codeLength;
- mv.visitCode();
+ mv.visitCode();
- // 1st phase: finds the labels
- int label;
- Label[] labels = new Label[codeLength + 2];
- readLabel(codeLength + 1, labels);
- while (v < codeEnd) {
- w = v - codeStart;
- int opcode = b[v] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- v += 1;
- break;
- case ClassWriter.LABEL_INSN:
- readLabel(w + readShort(v + 1), labels);
- v += 3;
- break;
- case ClassWriter.LABELW_INSN:
- readLabel(w + readInt(v + 1), labels);
- v += 5;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[v + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- v += 6;
- } else {
- v += 4;
- }
- break;
- case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes*
- v = v + 4 - (w & 3);
- // reads instruction
- readLabel(w + readInt(v), labels);
- j = readInt(v + 8) - readInt(v + 4) + 1;
- v += 12;
- for (; j > 0; --j) {
- readLabel(w + readInt(v), labels);
- v += 4;
- }
- break;
- case ClassWriter.LOOK_INSN:
- // skips 0 to 3 padding bytes*
- v = v + 4 - (w & 3);
- // reads instruction
- readLabel(w + readInt(v), labels);
- j = readInt(v + 4);
- v += 8;
- for (; j > 0; --j) {
- readLabel(w + readInt(v + 4), labels);
- v += 8;
- }
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- v += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- v += 3;
- break;
- case ClassWriter.ITFDYNMETH_INSN:
- v += 5;
- break;
- // case MANA_INSN:
- default:
- v += 4;
- break;
- }
- }
- // parses the try catch entries
- j = readUnsignedShort(v);
- v += 2;
- for (; j > 0; --j) {
- Label start = readLabel(readUnsignedShort(v), labels);
- Label end = readLabel(readUnsignedShort(v + 2), labels);
- Label handler = readLabel(readUnsignedShort(v + 4), labels);
- int type = readUnsignedShort(v + 6);
- if (type == 0) {
- mv.visitTryCatchBlock(start, end, handler, null);
- } else {
- mv.visitTryCatchBlock(start,
- end,
- handler,
- readUTF8(items[type], c));
- }
- v += 8;
- }
- // parses the local variable, line number tables, and code
- // attributes
- int varTable = 0;
- int varTypeTable = 0;
- int stackMap = 0;
- int frameCount = 0;
- int frameMode = 0;
- int frameOffset = 0;
- int frameLocalCount = 0;
- int frameLocalDiff = 0;
- int frameStackCount = 0;
- Object[] frameLocal = null;
- Object[] frameStack = null;
- boolean zip = true;
- cattrs = null;
- j = readUnsignedShort(v);
- v += 2;
- for (; j > 0; --j) {
- attrName = readUTF8(v, c);
- if ("LocalVariableTable".equals(attrName)) {
- if (!skipDebug) {
- varTable = v + 6;
- k = readUnsignedShort(v + 6);
- w = v + 8;
- for (; k > 0; --k) {
- label = readUnsignedShort(w);
- if (labels[label] == null) {
- readLabel(label, labels).status |= Label.DEBUG;
- }
- label += readUnsignedShort(w + 2);
- if (labels[label] == null) {
- readLabel(label, labels).status |= Label.DEBUG;
- }
- w += 10;
- }
+ // 1st phase: finds the labels
+ int label;
+ Label[] labels = new Label[codeLength + 2];
+ readLabel(codeLength + 1, labels);
+ while (v < codeEnd)
+ {
+ w = v - codeStart;
+ int opcode = b[v] & 0xFF;
+ switch (ClassWriter.TYPE[opcode])
+ {
+ case ClassWriter.NOARG_INSN :
+ case ClassWriter.IMPLVAR_INSN :
+ v += 1;
+ break;
+ case ClassWriter.LABEL_INSN :
+ readLabel(w + readShort(v + 1), labels);
+ v += 3;
+ break;
+ case ClassWriter.LABELW_INSN :
+ readLabel(w + readInt(v + 1), labels);
+ v += 5;
+ break;
+ case ClassWriter.WIDE_INSN :
+ opcode = b[v + 1] & 0xFF;
+ if (opcode == Opcodes.IINC)
+ {
+ v += 6;
+ }
+ else
+ {
+ v += 4;
+ }
+ break;
+ case ClassWriter.TABL_INSN :
+ // skips 0 to 3 padding bytes*
+ v = v + 4 - (w & 3);
+ // reads instruction
+ readLabel(w + readInt(v), labels);
+ j = readInt(v + 8) - readInt(v + 4) + 1;
+ v += 12;
+ for (; j > 0; --j)
+ {
+ readLabel(w + readInt(v), labels);
+ v += 4;
+ }
+ break;
+ case ClassWriter.LOOK_INSN :
+ // skips 0 to 3 padding bytes*
+ v = v + 4 - (w & 3);
+ // reads instruction
+ readLabel(w + readInt(v), labels);
+ j = readInt(v + 4);
+ v += 8;
+ for (; j > 0; --j)
+ {
+ readLabel(w + readInt(v + 4), labels);
+ v += 8;
+ }
+ break;
+ case ClassWriter.VAR_INSN :
+ case ClassWriter.SBYTE_INSN :
+ case ClassWriter.LDC_INSN :
+ v += 2;
+ break;
+ case ClassWriter.SHORT_INSN :
+ case ClassWriter.LDCW_INSN :
+ case ClassWriter.FIELDORMETH_INSN :
+ case ClassWriter.TYPE_INSN :
+ case ClassWriter.IINC_INSN :
+ v += 3;
+ break;
+ case ClassWriter.ITFDYNMETH_INSN :
+ v += 5;
+ break;
+ // case MANA_INSN:
+ default :
+ v += 4;
+ break;
+ }
+ }
+ // parses the try catch entries
+ j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j)
+ {
+ Label start = readLabel(readUnsignedShort(v), labels);
+ Label end = readLabel(readUnsignedShort(v + 2), labels);
+ Label handler = readLabel(readUnsignedShort(v + 4), labels);
+ int type = readUnsignedShort(v + 6);
+ if (type == 0)
+ {
+ mv.visitTryCatchBlock(start, end, handler, null);
+ }
+ else
+ {
+ mv.visitTryCatchBlock(start, end, handler, readUTF8(items[type], c));
+ }
+ v += 8;
+ }
+ // parses the local variable, line number tables, and code
+ // attributes
+ int varTable = 0;
+ int varTypeTable = 0;
+ int stackMap = 0;
+ int frameCount = 0;
+ int frameMode = 0;
+ int frameOffset = 0;
+ int frameLocalCount = 0;
+ int frameLocalDiff = 0;
+ int frameStackCount = 0;
+ Object[] frameLocal = null;
+ Object[] frameStack = null;
+ boolean zip = true;
+ cattrs = null;
+ j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j)
+ {
+ attrName = readUTF8(v, c);
+ if ("LocalVariableTable".equals(attrName))
+ {
+ if (!skipDebug)
+ {
+ varTable = v + 6;
+ k = readUnsignedShort(v + 6);
+ w = v + 8;
+ for (; k > 0; --k)
+ {
+ label = readUnsignedShort(w);
+ if (labels[label] == null)
+ {
+ readLabel(label, labels).status |= Label.DEBUG;
}
- } else if ("LocalVariableTypeTable".equals(attrName)) {
- varTypeTable = v + 6;
- } else if ("LineNumberTable".equals(attrName)) {
- if (!skipDebug) {
- k = readUnsignedShort(v + 6);
- w = v + 8;
- for (; k > 0; --k) {
- label = readUnsignedShort(w);
- if (labels[label] == null) {
- readLabel(label, labels).status |= Label.DEBUG;
- }
- labels[label].line = readUnsignedShort(w + 2);
- w += 4;
- }
+ label += readUnsignedShort(w + 2);
+ if (labels[label] == null)
+ {
+ readLabel(label, labels).status |= Label.DEBUG;
}
- } else if (FRAMES && "StackMapTable".equals(attrName)) {
- if ((flags & SKIP_FRAMES) == 0) {
- stackMap = v + 8;
- frameCount = readUnsignedShort(v + 6);
+ w += 10;
+ }
+ }
+ }
+ else if ("LocalVariableTypeTable".equals(attrName))
+ {
+ varTypeTable = v + 6;
+ }
+ else if ("LineNumberTable".equals(attrName))
+ {
+ if (!skipDebug)
+ {
+ k = readUnsignedShort(v + 6);
+ w = v + 8;
+ for (; k > 0; --k)
+ {
+ label = readUnsignedShort(w);
+ if (labels[label] == null)
+ {
+ readLabel(label, labels).status |= Label.DEBUG;
}
- /*
- * here we do not extract the labels corresponding to
- * the attribute content. This would require a full
- * parsing of the attribute, which would need to be
- * repeated in the second phase (see below). Instead the
- * content of the attribute is read one frame at a time
- * (i.e. after a frame has been visited, the next frame
- * is read), and the labels it contains are also
- * extracted one frame at a time. Thanks to the ordering
- * of frames, having only a "one frame lookahead" is not
- * a problem, i.e. it is not possible to see an offset
- * smaller than the offset of the current insn and for
- * which no Label exist.
- */
- // TODO true for frame offsets,
- // but for UNINITIALIZED type offsets?
- } else if (FRAMES && "StackMap".equals(attrName)) {
- if ((flags & SKIP_FRAMES) == 0) {
- stackMap = v + 8;
- frameCount = readUnsignedShort(v + 6);
- zip = false;
+ labels[label].line = readUnsignedShort(w + 2);
+ w += 4;
+ }
+ }
+ }
+ else if (FRAMES && "StackMapTable".equals(attrName))
+ {
+ if ((flags & SKIP_FRAMES) == 0)
+ {
+ stackMap = v + 8;
+ frameCount = readUnsignedShort(v + 6);
+ }
+ /*
+ * here we do not extract the labels corresponding to
+ * the attribute content. This would require a full
+ * parsing of the attribute, which would need to be
+ * repeated in the second phase (see below). Instead the
+ * content of the attribute is read one frame at a time
+ * (i.e. after a frame has been visited, the next frame
+ * is read), and the labels it contains are also
+ * extracted one frame at a time. Thanks to the ordering
+ * of frames, having only a "one frame lookahead" is not
+ * a problem, i.e. it is not possible to see an offset
+ * smaller than the offset of the current insn and for
+ * which no Label exist.
+ */
+ // TODO true for frame offsets,
+ // but for UNINITIALIZED type offsets?
+ }
+ else if (FRAMES && "StackMap".equals(attrName))
+ {
+ if ((flags & SKIP_FRAMES) == 0)
+ {
+ stackMap = v + 8;
+ frameCount = readUnsignedShort(v + 6);
+ zip = false;
+ }
+ /*
+ * IMPORTANT! here we assume that the frames are
+ * ordered, as in the StackMapTable attribute, although
+ * this is not guaranteed by the attribute format.
+ */
+ }
+ else
+ {
+ for (k = 0; k < attrs.length; ++k)
+ {
+ if (attrs[k].type.equals(attrName))
+ {
+ attr = attrs[k].read(this, v + 6, readInt(v + 2), c, codeStart - 8, labels);
+ if (attr != null)
+ {
+ attr.next = cattrs;
+ cattrs = attr;
}
- /*
- * IMPORTANT! here we assume that the frames are
- * ordered, as in the StackMapTable attribute, although
- * this is not guaranteed by the attribute format.
- */
- } else {
- for (k = 0; k < attrs.length; ++k) {
- if (attrs[k].type.equals(attrName)) {
- attr = attrs[k].read(this,
- v + 6,
- readInt(v + 2),
- c,
- codeStart - 8,
- labels);
- if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
- }
- }
- }
- }
- v += 6 + readInt(v + 2);
- }
+ }
+ }
+ }
+ v += 6 + readInt(v + 2);
+ }
- // 2nd phase: visits each instruction
- if (FRAMES && stackMap != 0) {
- // creates the very first (implicit) frame from the method
- // descriptor
- frameLocal = new Object[maxLocals];
- frameStack = new Object[maxStack];
- if (unzip) {
- int local = 0;
- if ((access & Opcodes.ACC_STATIC) == 0) {
- if ("<init>".equals(name)) {
- frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
- } else {
- frameLocal[local++] = readClass(header + 2, c);
- }
+ // 2nd phase: visits each instruction
+ if (FRAMES && stackMap != 0)
+ {
+ // creates the very first (implicit) frame from the method
+ // descriptor
+ frameLocal = new Object[maxLocals];
+ frameStack = new Object[maxStack];
+ if (unzip)
+ {
+ int local = 0;
+ if ((access & Opcodes.ACC_STATIC) == 0)
+ {
+ if ("<init>".equals(name))
+ {
+ frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
+ }
+ else
+ {
+ frameLocal[local++] = readClass(header + 2, c);
+ }
+ }
+ j = 1;
+ loop : while (true)
+ {
+ k = j;
+ switch (desc.charAt(j++))
+ {
+ case 'Z' :
+ case 'C' :
+ case 'B' :
+ case 'S' :
+ case 'I' :
+ frameLocal[local++] = Opcodes.INTEGER;
+ break;
+ case 'F' :
+ frameLocal[local++] = Opcodes.FLOAT;
+ break;
+ case 'J' :
+ frameLocal[local++] = Opcodes.LONG;
+ break;
+ case 'D' :
+ frameLocal[local++] = Opcodes.DOUBLE;
+ break;
+ case '[' :
+ while (desc.charAt(j) == '[')
+ {
+ ++j;
+ }
+ if (desc.charAt(j) == 'L')
+ {
+ ++j;
+ while (desc.charAt(j) != ';')
+ {
+ ++j;
+ }
+ }
+ frameLocal[local++] = desc.substring(k, ++j);
+ break;
+ case 'L' :
+ while (desc.charAt(j) != ';')
+ {
+ ++j;
+ }
+ frameLocal[local++] = desc.substring(k + 1, j++);
+ break;
+ default :
+ break loop;
+ }
+ }
+ frameLocalCount = local;
+ }
+ /*
+ * for the first explicit frame the offset is not
+ * offset_delta + 1 but only offset_delta; setting the
+ * implicit frame offset to -1 allow the use of the
+ * "offset_delta + 1" rule in all cases
+ */
+ frameOffset = -1;
+ }
+ v = codeStart;
+ Label l;
+ while (v < codeEnd)
+ {
+ w = v - codeStart;
+
+ l = labels[w];
+ if (l != null)
+ {
+ mv.visitLabel(l);
+ if (!skipDebug && l.line > 0)
+ {
+ mv.visitLineNumber(l.line, l);
+ }
+ }
+
+ while (FRAMES && frameLocal != null && (frameOffset == w || frameOffset == -1))
+ {
+ // if there is a frame for this offset,
+ // makes the visitor visit it,
+ // and reads the next frame if there is one.
+ if (!zip || unzip)
+ {
+ mv.visitFrame(Opcodes.F_NEW, frameLocalCount, frameLocal, frameStackCount, frameStack);
+ }
+ else if (frameOffset != -1)
+ {
+ mv.visitFrame(frameMode, frameLocalDiff, frameLocal, frameStackCount, frameStack);
+ }
+
+ if (frameCount > 0)
+ {
+ int tag, delta, n;
+ if (zip)
+ {
+ tag = b[stackMap++] & 0xFF;
+ }
+ else
+ {
+ tag = MethodWriter.FULL_FRAME;
+ frameOffset = -1;
+ }
+ frameLocalDiff = 0;
+ if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)
+ {
+ delta = tag;
+ frameMode = Opcodes.F_SAME;
+ frameStackCount = 0;
+ }
+ else if (tag < MethodWriter.RESERVED)
+ {
+ delta = tag - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
+ stackMap = readFrameType(frameStack, 0, stackMap, c, labels);
+ frameMode = Opcodes.F_SAME1;
+ frameStackCount = 1;
+ }
+ else
+ {
+ delta = readUnsignedShort(stackMap);
+ stackMap += 2;
+ if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
+ {
+ stackMap = readFrameType(frameStack, 0, stackMap, c, labels);
+ frameMode = Opcodes.F_SAME1;
+ frameStackCount = 1;
}
- j = 1;
- loop: while (true) {
- k = j;
- switch (desc.charAt(j++)) {
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- frameLocal[local++] = Opcodes.INTEGER;
- break;
- case 'F':
- frameLocal[local++] = Opcodes.FLOAT;
- break;
- case 'J':
- frameLocal[local++] = Opcodes.LONG;
- break;
- case 'D':
- frameLocal[local++] = Opcodes.DOUBLE;
- break;
- case '[':
- while (desc.charAt(j) == '[') {
- ++j;
- }
- if (desc.charAt(j) == 'L') {
- ++j;
- while (desc.charAt(j) != ';') {
- ++j;
- }
- }
- frameLocal[local++] = desc.substring(k, ++j);
- break;
- case 'L':
- while (desc.charAt(j) != ';') {
- ++j;
- }
- frameLocal[local++] = desc.substring(k + 1,
- j++);
- break;
- default:
- break loop;
- }
+ else if (tag >= MethodWriter.CHOP_FRAME && tag < MethodWriter.SAME_FRAME_EXTENDED)
+ {
+ frameMode = Opcodes.F_CHOP;
+ frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED - tag;
+ frameLocalCount -= frameLocalDiff;
+ frameStackCount = 0;
}
- frameLocalCount = local;
- }
- /*
- * for the first explicit frame the offset is not
- * offset_delta + 1 but only offset_delta; setting the
- * implicit frame offset to -1 allow the use of the
- * "offset_delta + 1" rule in all cases
- */
- frameOffset = -1;
- }
- v = codeStart;
- Label l;
- while (v < codeEnd) {
- w = v - codeStart;
-
- l = labels[w];
- if (l != null) {
- mv.visitLabel(l);
- if (!skipDebug && l.line > 0) {
- mv.visitLineNumber(l.line, l);
+ else if (tag == MethodWriter.SAME_FRAME_EXTENDED)
+ {
+ frameMode = Opcodes.F_SAME;
+ frameStackCount = 0;
}
- }
-
- while (FRAMES && frameLocal != null
- && (frameOffset == w || frameOffset == -1))
- {
- // if there is a frame for this offset,
- // makes the visitor visit it,
- // and reads the next frame if there is one.
- if (!zip || unzip) {
- mv.visitFrame(Opcodes.F_NEW,
- frameLocalCount,
- frameLocal,
- frameStackCount,
- frameStack);
- } else if (frameOffset != -1) {
- mv.visitFrame(frameMode,
- frameLocalDiff,
- frameLocal,
- frameStackCount,
- frameStack);
+ else if (tag < MethodWriter.FULL_FRAME)
+ {
+ j = unzip ? frameLocalCount : 0;
+ for (k = tag - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--)
+ {
+ stackMap = readFrameType(frameLocal, j++, stackMap, c, labels);
+ }
+ frameMode = Opcodes.F_APPEND;
+ frameLocalDiff = tag - MethodWriter.SAME_FRAME_EXTENDED;
+ frameLocalCount += frameLocalDiff;
+ frameStackCount = 0;
}
+ else
+ { // if (tag == FULL_FRAME) {
+ frameMode = Opcodes.F_FULL;
+ n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap);
+ stackMap += 2;
+ for (j = 0; n > 0; n--)
+ {
+ stackMap = readFrameType(frameLocal, j++, stackMap, c, labels);
+ }
+ n = frameStackCount = readUnsignedShort(stackMap);
+ stackMap += 2;
+ for (j = 0; n > 0; n--)
+ {
+ stackMap = readFrameType(frameStack, j++, stackMap, c, labels);
+ }
+ }
+ }
+ frameOffset += delta + 1;
+ readLabel(frameOffset, labels);
- if (frameCount > 0) {
- int tag, delta, n;
- if (zip) {
- tag = b[stackMap++] & 0xFF;
- } else {
- tag = MethodWriter.FULL_FRAME;
- frameOffset = -1;
- }
- frameLocalDiff = 0;
- if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)
- {
- delta = tag;
- frameMode = Opcodes.F_SAME;
- frameStackCount = 0;
- } else if (tag < MethodWriter.RESERVED) {
- delta = tag
- - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
- stackMap = readFrameType(frameStack,
- 0,
- stackMap,
- c,
- labels);
- frameMode = Opcodes.F_SAME1;
- frameStackCount = 1;
- } else {
- delta = readUnsignedShort(stackMap);
- stackMap += 2;
- if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
- {
- stackMap = readFrameType(frameStack,
- 0,
- stackMap,
- c,
- labels);
- frameMode = Opcodes.F_SAME1;
- frameStackCount = 1;
- } else if (tag >= MethodWriter.CHOP_FRAME
- && tag < MethodWriter.SAME_FRAME_EXTENDED)
- {
- frameMode = Opcodes.F_CHOP;
- frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED
- - tag;
- frameLocalCount -= frameLocalDiff;
- frameStackCount = 0;
- } else if (tag == MethodWriter.SAME_FRAME_EXTENDED)
- {
- frameMode = Opcodes.F_SAME;
- frameStackCount = 0;
- } else if (tag < MethodWriter.FULL_FRAME) {
- j = unzip ? frameLocalCount : 0;
- for (k = tag
- - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--)
- {
- stackMap = readFrameType(frameLocal,
- j++,
- stackMap,
- c,
- labels);
- }
- frameMode = Opcodes.F_APPEND;
- frameLocalDiff = tag
- - MethodWriter.SAME_FRAME_EXTENDED;
- frameLocalCount += frameLocalDiff;
- frameStackCount = 0;
- } else { // if (tag == FULL_FRAME) {
- frameMode = Opcodes.F_FULL;
- n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap);
- stackMap += 2;
- for (j = 0; n > 0; n--) {
- stackMap = readFrameType(frameLocal,
- j++,
- stackMap,
- c,
- labels);
- }
- n = frameStackCount = readUnsignedShort(stackMap);
- stackMap += 2;
- for (j = 0; n > 0; n--) {
- stackMap = readFrameType(frameStack,
- j++,
- stackMap,
- c,
- labels);
- }
- }
- }
- frameOffset += delta + 1;
- readLabel(frameOffset, labels);
+ --frameCount;
+ }
+ else
+ {
+ frameLocal = null;
+ }
+ }
- --frameCount;
- } else {
- frameLocal = null;
+ int opcode = b[v] & 0xFF;
+ switch (ClassWriter.TYPE[opcode])
+ {
+ case ClassWriter.NOARG_INSN :
+ mv.visitInsn(opcode);
+ v += 1;
+ break;
+ case ClassWriter.IMPLVAR_INSN :
+ if (opcode > Opcodes.ISTORE)
+ {
+ opcode -= 59; // ISTORE_0
+ mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), opcode & 0x3);
+ }
+ else
+ {
+ opcode -= 26; // ILOAD_0
+ mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);
+ }
+ v += 1;
+ break;
+ case ClassWriter.LABEL_INSN :
+ mv.visitJumpInsn(opcode, labels[w + readShort(v + 1)]);
+ v += 3;
+ break;
+ case ClassWriter.LABELW_INSN :
+ mv.visitJumpInsn(opcode - 33, labels[w + readInt(v + 1)]);
+ v += 5;
+ break;
+ case ClassWriter.WIDE_INSN :
+ opcode = b[v + 1] & 0xFF;
+ if (opcode == Opcodes.IINC)
+ {
+ mv.visitIincInsn(readUnsignedShort(v + 2), readShort(v + 4));
+ v += 6;
+ }
+ else
+ {
+ mv.visitVarInsn(opcode, readUnsignedShort(v + 2));
+ v += 4;
+ }
+ break;
+ case ClassWriter.TABL_INSN :
+ // skips 0 to 3 padding bytes
+ v = v + 4 - (w & 3);
+ // reads instruction
+ label = w + readInt(v);
+ int min = readInt(v + 4);
+ int max = readInt(v + 8);
+ v += 12;
+ Label[] table = new Label[max - min + 1];
+ for (j = 0; j < table.length; ++j)
+ {
+ table[j] = labels[w + readInt(v)];
+ v += 4;
+ }
+ mv.visitTableSwitchInsn(min, max, labels[label], table);
+ break;
+ case ClassWriter.LOOK_INSN :
+ // skips 0 to 3 padding bytes
+ v = v + 4 - (w & 3);
+ // reads instruction
+ label = w + readInt(v);
+ j = readInt(v + 4);
+ v += 8;
+ int[] keys = new int[j];
+ Label[] values = new Label[j];
+ for (j = 0; j < keys.length; ++j)
+ {
+ keys[j] = readInt(v);
+ values[j] = labels[w + readInt(v + 4)];
+ v += 8;
+ }
+ mv.visitLookupSwitchInsn(labels[label], keys, values);
+ break;
+ case ClassWriter.VAR_INSN :
+ mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
+ v += 2;
+ break;
+ case ClassWriter.SBYTE_INSN :
+ mv.visitIntInsn(opcode, b[v + 1]);
+ v += 2;
+ break;
+ case ClassWriter.SHORT_INSN :
+ mv.visitIntInsn(opcode, readShort(v + 1));
+ v += 3;
+ break;
+ case ClassWriter.LDC_INSN :
+ mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
+ v += 2;
+ break;
+ case ClassWriter.LDCW_INSN :
+ mv.visitLdcInsn(readConst(readUnsignedShort(v + 1), c));
+ v += 3;
+ break;
+ case ClassWriter.FIELDORMETH_INSN :
+ case ClassWriter.ITFDYNMETH_INSN :
+ int cpIndex = items[readUnsignedShort(v + 1)];
+ String iowner;
+ // INVOKEDYNAMIC is receiverless
+ if (opcode == Opcodes.INVOKEDYNAMIC)
+ {
+ iowner = Opcodes.INVOKEDYNAMIC_OWNER;
+ }
+ else
+ {
+ iowner = readClass(cpIndex, c);
+ cpIndex = items[readUnsignedShort(cpIndex + 2)];
+ }
+ String iname = readUTF8(cpIndex, c);
+ String idesc = readUTF8(cpIndex + 2, c);
+ if (opcode < Opcodes.INVOKEVIRTUAL)
+ {
+ mv.visitFieldInsn(opcode, iowner, iname, idesc);
+ }
+ else
+ {
+ mv.visitMethodInsn(opcode, iowner, iname, idesc);
+ }
+ if (opcode == Opcodes.INVOKEINTERFACE || opcode == Opcodes.INVOKEDYNAMIC)
+ {
+ v += 5;
+ }
+ else
+ {
+ v += 3;
+ }
+ break;
+ case ClassWriter.TYPE_INSN :
+ mv.visitTypeInsn(opcode, readClass(v + 1, c));
+ v += 3;
+ break;
+ case ClassWriter.IINC_INSN :
+ mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
+ v += 3;
+ break;
+ // case MANA_INSN:
+ default :
+ mv.visitMultiANewArrayInsn(readClass(v + 1, c), b[v + 3] & 0xFF);
+ v += 4;
+ break;
+ }
+ }
+ l = labels[codeEnd - codeStart];
+ if (l != null)
+ {
+ mv.visitLabel(l);
+ }
+ // visits the local variable tables
+ if (!skipDebug && varTable != 0)
+ {
+ int[] typeTable = null;
+ if (varTypeTable != 0)
+ {
+ k = readUnsignedShort(varTypeTable) * 3;
+ w = varTypeTable + 2;
+ typeTable = new int[k];
+ while (k > 0)
+ {
+ typeTable[--k] = w + 6; // signature
+ typeTable[--k] = readUnsignedShort(w + 8); // index
+ typeTable[--k] = readUnsignedShort(w); // start
+ w += 10;
+ }
+ }
+ k = readUnsignedShort(varTable);
+ w = varTable + 2;
+ for (; k > 0; --k)
+ {
+ int start = readUnsignedShort(w);
+ int length = readUnsignedShort(w + 2);
+ int index = readUnsignedShort(w + 8);
+ String vsignature = null;
+ if (typeTable != null)
+ {
+ for (int a = 0; a < typeTable.length; a += 3)
+ {
+ if (typeTable[a] == start && typeTable[a + 1] == index)
+ {
+ vsignature = readUTF8(typeTable[a + 2], c);
+ break;
}
- }
-
- int opcode = b[v] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- mv.visitInsn(opcode);
- v += 1;
- break;
- case ClassWriter.IMPLVAR_INSN:
- if (opcode > Opcodes.ISTORE) {
- opcode -= 59; // ISTORE_0
- mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
- opcode & 0x3);
- } else {
- opcode -= 26; // ILOAD_0
- mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2),
- opcode & 0x3);
- }
- v += 1;
- break;
- case ClassWriter.LABEL_INSN:
- mv.visitJumpInsn(opcode, labels[w
- + readShort(v + 1)]);
- v += 3;
- break;
- case ClassWriter.LABELW_INSN:
- mv.visitJumpInsn(opcode - 33, labels[w
- + readInt(v + 1)]);
- v += 5;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[v + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- mv.visitIincInsn(readUnsignedShort(v + 2),
- readShort(v + 4));
- v += 6;
- } else {
- mv.visitVarInsn(opcode,
- readUnsignedShort(v + 2));
- v += 4;
- }
- break;
- case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes
- v = v + 4 - (w & 3);
- // reads instruction
- label = w + readInt(v);
- int min = readInt(v + 4);
- int max = readInt(v + 8);
- v += 12;
- Label[] table = new Label[max - min + 1];
- for (j = 0; j < table.length; ++j) {
- table[j] = labels[w + readInt(v)];
- v += 4;
- }
- mv.visitTableSwitchInsn(min,
- max,
- labels[label],
- table);
- break;
- case ClassWriter.LOOK_INSN:
- // skips 0 to 3 padding bytes
- v = v + 4 - (w & 3);
- // reads instruction
- label = w + readInt(v);
- j = readInt(v + 4);
- v += 8;
- int[] keys = new int[j];
- Label[] values = new Label[j];
- for (j = 0; j < keys.length; ++j) {
- keys[j] = readInt(v);
- values[j] = labels[w + readInt(v + 4)];
- v += 8;
- }
- mv.visitLookupSwitchInsn(labels[label],
- keys,
- values);
- break;
- case ClassWriter.VAR_INSN:
- mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
- v += 2;
- break;
- case ClassWriter.SBYTE_INSN:
- mv.visitIntInsn(opcode, b[v + 1]);
- v += 2;
- break;
- case ClassWriter.SHORT_INSN:
- mv.visitIntInsn(opcode, readShort(v + 1));
- v += 3;
- break;
- case ClassWriter.LDC_INSN:
- mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
- v += 2;
- break;
- case ClassWriter.LDCW_INSN:
- mv.visitLdcInsn(readConst(readUnsignedShort(v + 1),
- c));
- v += 3;
- break;
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.ITFDYNMETH_INSN:
- int cpIndex = items[readUnsignedShort(v + 1)];
- String iowner;
- // INVOKEDYNAMIC is receiverless
- if (opcode == Opcodes.INVOKEDYNAMIC) {
- iowner = Opcodes.INVOKEDYNAMIC_OWNER;
- } else {
- iowner = readClass(cpIndex, c);
- cpIndex = items[readUnsignedShort(cpIndex + 2)];
- }
- String iname = readUTF8(cpIndex, c);
- String idesc = readUTF8(cpIndex + 2, c);
- if (opcode < Opcodes.INVOKEVIRTUAL) {
- mv.visitFieldInsn(opcode, iowner, iname, idesc);
- } else {
- mv.visitMethodInsn(opcode, iowner, iname, idesc);
- }
- if (opcode == Opcodes.INVOKEINTERFACE || opcode == Opcodes.INVOKEDYNAMIC) {
- v += 5;
- } else {
- v += 3;
- }
- break;
- case ClassWriter.TYPE_INSN:
- mv.visitTypeInsn(opcode, readClass(v + 1, c));
- v += 3;
- break;
- case ClassWriter.IINC_INSN:
- mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
- v += 3;
- break;
- // case MANA_INSN:
- default:
- mv.visitMultiANewArrayInsn(readClass(v + 1, c),
- b[v + 3] & 0xFF);
- v += 4;
- break;
- }
- }
- l = labels[codeEnd - codeStart];
- if (l != null) {
- mv.visitLabel(l);
- }
- // visits the local variable tables
- if (!skipDebug && varTable != 0) {
- int[] typeTable = null;
- if (varTypeTable != 0) {
- k = readUnsignedShort(varTypeTable) * 3;
- w = varTypeTable + 2;
- typeTable = new int[k];
- while (k > 0) {
- typeTable[--k] = w + 6; // signature
- typeTable[--k] = readUnsignedShort(w + 8); // index
- typeTable[--k] = readUnsignedShort(w); // start
- w += 10;
- }
- }
- k = readUnsignedShort(varTable);
- w = varTable + 2;
- for (; k > 0; --k) {
- int start = readUnsignedShort(w);
- int length = readUnsignedShort(w + 2);
- int index = readUnsignedShort(w + 8);
- String vsignature = null;
- if (typeTable != null) {
- for (int a = 0; a < typeTable.length; a += 3) {
- if (typeTable[a] == start
- && typeTable[a + 1] == index)
- {
- vsignature = readUTF8(typeTable[a + 2], c);
- break;
- }
- }
- }
- mv.visitLocalVariable(readUTF8(w + 4, c),
- readUTF8(w + 6, c),
- vsignature,
- labels[start],
- labels[start + length],
- index);
- w += 10;
- }
- }
- // visits the other attributes
- while (cattrs != null) {
- attr = cattrs.next;
- cattrs.next = null;
- mv.visitAttribute(cattrs);
- cattrs = attr;
- }
- // visits the max stack and max locals values
- mv.visitMaxs(maxStack, maxLocals);
+ }
+ }
+ mv.visitLocalVariable(readUTF8(w + 4, c), readUTF8(w + 6, c), vsignature, labels[start], labels[start
+ + length], index);
+ w += 10;
+ }
}
-
- if (mv != null) {
- mv.visitEnd();
+ // visits the other attributes
+ while (cattrs != null)
+ {
+ attr = cattrs.next;
+ cattrs.next = null;
+ mv.visitAttribute(cattrs);
+ cattrs = attr;
}
- }
+ // visits the max stack and max locals values
+ mv.visitMaxs(maxStack, maxLocals);
+ }
- // visits the end of the class
- classVisitor.visitEnd();
- }
+ if (mv != null)
+ {
+ mv.visitEnd();
+ }
+ }
- /**
- * Reads parameter annotations and makes the given visitor visit them.
- *
- * @param v start offset in {@link #b b} of the annotations to be read.
- * @param desc the method descriptor.
- * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
- * {@link #readClass(int,char[]) readClass} or
- * {@link #readConst readConst}.
- * @param visible <tt>true</tt> if the annotations to be read are visible
- * at runtime.
- * @param mv the visitor that must visit the annotations.
- */
- private void readParameterAnnotations(
- int v,
- final String desc,
- final char[] buf,
- final boolean visible,
- final MethodVisitor mv)
- {
- int i;
- int n = b[v++] & 0xFF;
- // workaround for a bug in javac (javac compiler generates a parameter
- // annotation array whose size is equal to the number of parameters in
- // the Java source file, while it should generate an array whose size is
- // equal to the number of parameters in the method descriptor - which
- // includes the synthetic parameters added by the compiler). This work-
- // around supposes that the synthetic parameters are the first ones.
- int synthetics = Type.getArgumentTypes(desc).length - n;
- AnnotationVisitor av;
- for (i = 0; i < synthetics; ++i) {
- // virtual annotation to detect synthetic parameters in MethodWriter
- av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
- if (av != null) {
- av.visitEnd();
- }
- }
- for (; i < n + synthetics; ++i) {
- int j = readUnsignedShort(v);
- v += 2;
- for (; j > 0; --j) {
- av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);
- v = readAnnotationValues(v + 2, buf, true, av);
- }
- }
- }
+ // visits the end of the class
+ classVisitor.visitEnd();
+ }
- /**
- * Reads the values of an annotation and makes the given visitor visit them.
- *
- * @param v the start offset in {@link #b b} of the values to be read
- * (including the unsigned short that gives the number of values).
- * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
- * {@link #readClass(int,char[]) readClass} or
- * {@link #readConst readConst}.
- * @param named if the annotation values are named or not.
- * @param av the visitor that must visit the values.
- * @return the end offset of the annotation values.
- */
- private int readAnnotationValues(
- int v,
- final char[] buf,
- final boolean named,
- final AnnotationVisitor av)
- {
- int i = readUnsignedShort(v);
- v += 2;
- if (named) {
- for (; i > 0; --i) {
- v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);
- }
- } else {
- for (; i > 0; --i) {
- v = readAnnotationValue(v, buf, null, av);
- }
- }
- if (av != null) {
+ /**
+ * Reads parameter annotations and makes the given visitor visit them.
+ *
+ * @param v start offset in {@link #b b} of the annotations to be read.
+ * @param desc the method descriptor.
+ * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or
+ * {@link #readConst readConst}.
+ * @param visible <tt>true</tt> if the annotations to be read are visible
+ * at runtime.
+ * @param mv the visitor that must visit the annotations.
+ */
+ private void readParameterAnnotations(int v, final String desc, final char[] buf, final boolean visible,
+ final MethodVisitor mv)
+ {
+ int i;
+ int n = b[v++] & 0xFF;
+ // workaround for a bug in javac (javac compiler generates a parameter
+ // annotation array whose size is equal to the number of parameters in
+ // the Java source file, while it should generate an array whose size is
+ // equal to the number of parameters in the method descriptor - which
+ // includes the synthetic parameters added by the compiler). This work-
+ // around supposes that the synthetic parameters are the first ones.
+ int synthetics = Type.getArgumentTypes(desc).length - n;
+ AnnotationVisitor av;
+ for (i = 0; i < synthetics; ++i)
+ {
+ // virtual annotation to detect synthetic parameters in MethodWriter
+ av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
+ if (av != null)
+ {
av.visitEnd();
- }
- return v;
- }
+ }
+ }
+ for (; i < n + synthetics; ++i)
+ {
+ int j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j)
+ {
+ av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);
+ v = readAnnotationValues(v + 2, buf, true, av);
+ }
+ }
+ }
- /**
- * Reads a value of an annotation and makes the given visitor visit it.
- *
- * @param v the start offset in {@link #b b} of the value to be read (<i>not
- * including the value name constant pool index</i>).
- * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
- * {@link #readClass(int,char[]) readClass} or
- * {@link #readConst readConst}.
- * @param name the name of the value to be read.
- * @param av the visitor that must visit the value.
- * @return the end offset of the annotation value.
- */
- private int readAnnotationValue(
- int v,
- final char[] buf,
- final String name,
- final AnnotationVisitor av)
- {
- int i;
- if (av == null) {
- switch (b[v] & 0xFF) {
- case 'e': // enum_const_value
- return v + 5;
- case '@': // annotation_value
- return readAnnotationValues(v + 3, buf, true, null);
- case '[': // array_value
- return readAnnotationValues(v + 1, buf, false, null);
- default:
- return v + 3;
+ /**
+ * Reads the values of an annotation and makes the given visitor visit them.
+ *
+ * @param v the start offset in {@link #b b} of the values to be read
+ * (including the unsigned short that gives the number of values).
+ * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or
+ * {@link #readConst readConst}.
+ * @param named if the annotation values are named or not.
+ * @param av the visitor that must visit the values.
+ * @return the end offset of the annotation values.
+ */
+ private int readAnnotationValues(int v, final char[] buf, final boolean named, final AnnotationVisitor av)
+ {
+ int i = readUnsignedShort(v);
+ v += 2;
+ if (named)
+ {
+ for (; i > 0; --i)
+ {
+ v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);
+ }
+ }
+ else
+ {
+ for (; i > 0; --i)
+ {
+ v = readAnnotationValue(v, buf, null, av);
+ }
+ }
+ if (av != null)
+ {
+ av.visitEnd();
+ }
+ return v;
+ }
+
+ /**
+ * Reads a value of an annotation and makes the given visitor visit it.
+ *
+ * @param v the start offset in {@link #b b} of the value to be read (<i>not
+ * including the value name constant pool index</i>).
+ * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or
+ * {@link #readConst readConst}.
+ * @param name the name of the value to be read.
+ * @param av the visitor that must visit the value.
+ * @return the end offset of the annotation value.
+ */
+ private int readAnnotationValue(int v, final char[] buf, final String name, final AnnotationVisitor av)
+ {
+ int i;
+ if (av == null)
+ {
+ switch (b[v] & 0xFF)
+ {
+ case 'e' : // enum_const_value
+ return v + 5;
+ case '@' : // annotation_value
+ return readAnnotationValues(v + 3, buf, true, null);
+ case '[' : // array_value
+ return readAnnotationValues(v + 1, buf, false, null);
+ default :
+ return v + 3;
+ }
+ }
+ switch (b[v++] & 0xFF)
+ {
+ case 'I' : // pointer to CONSTANT_Integer
+ case 'J' : // pointer to CONSTANT_Long
+ case 'F' : // pointer to CONSTANT_Float
+ case 'D' : // pointer to CONSTANT_Double
+ av.visit(name, readConst(readUnsignedShort(v), buf));
+ v += 2;
+ break;
+ case 'B' : // pointer to CONSTANT_Byte
+ av.visit(name, new Byte((byte) readInt(items[readUnsignedShort(v)])));
+ v += 2;
+ break;
+ case 'Z' : // pointer to CONSTANT_Boolean
+ av.visit(name, readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE : Boolean.TRUE);
+ v += 2;
+ break;
+ case 'S' : // pointer to CONSTANT_Short
+ av.visit(name, new Short((short) readInt(items[readUnsignedShort(v)])));
+ v += 2;
+ break;
+ case 'C' : // pointer to CONSTANT_Char
+ av.visit(name, new Character((char) readInt(items[readUnsignedShort(v)])));
+ v += 2;
+ break;
+ case 's' : // pointer to CONSTANT_Utf8
+ av.visit(name, readUTF8(v, buf));
+ v += 2;
+ break;
+ case 'e' : // enum_const_value
+ av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
+ v += 4;
+ break;
+ case 'c' : // class_info
+ av.visit(name, Type.getType(readUTF8(v, buf)));
+ v += 2;
+ break;
+ case '@' : // annotation_value
+ v = readAnnotationValues(v + 2, buf, true, av.visitAnnotation(name, readUTF8(v, buf)));
+ break;
+ case '[' : // array_value
+ int size = readUnsignedShort(v);
+ v += 2;
+ if (size == 0)
+ {
+ return readAnnotationValues(v - 2, buf, false, av.visitArray(name));
}
- }
- switch (b[v++] & 0xFF) {
- case 'I': // pointer to CONSTANT_Integer
- case 'J': // pointer to CONSTANT_Long
- case 'F': // pointer to CONSTANT_Float
- case 'D': // pointer to CONSTANT_Double
- av.visit(name, readConst(readUnsignedShort(v), buf));
- v += 2;
- break;
- case 'B': // pointer to CONSTANT_Byte
- av.visit(name,
- new Byte((byte) readInt(items[readUnsignedShort(v)])));
- v += 2;
- break;
- case 'Z': // pointer to CONSTANT_Boolean
- av.visit(name, readInt(items[readUnsignedShort(v)]) == 0
- ? Boolean.FALSE
- : Boolean.TRUE);
- v += 2;
- break;
- case 'S': // pointer to CONSTANT_Short
- av.visit(name,
- new Short((short) readInt(items[readUnsignedShort(v)])));
- v += 2;
- break;
- case 'C': // pointer to CONSTANT_Char
- av.visit(name,
- new Character((char) readInt(items[readUnsignedShort(v)])));
- v += 2;
- break;
- case 's': // pointer to CONSTANT_Utf8
- av.visit(name, readUTF8(v, buf));
- v += 2;
- break;
- case 'e': // enum_const_value
- av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
- v += 4;
- break;
- case 'c': // class_info
- av.visit(name, Type.getType(readUTF8(v, buf)));
- v += 2;
- break;
- case '@': // annotation_value
- v = readAnnotationValues(v + 2,
- buf,
- true,
- av.visitAnnotation(name, readUTF8(v, buf)));
- break;
- case '[': // array_value
- int size = readUnsignedShort(v);
- v += 2;
- if (size == 0) {
- return readAnnotationValues(v - 2,
- buf,
- false,
- av.visitArray(name));
- }
- switch (this.b[v++] & 0xFF) {
- case 'B':
- byte[] bv = new byte[size];
- for (i = 0; i < size; i++) {
- bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
- v += 3;
- }
- av.visit(name, bv);
- --v;
- break;
- case 'Z':
- boolean[] zv = new boolean[size];
- for (i = 0; i < size; i++) {
- zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
- v += 3;
- }
- av.visit(name, zv);
- --v;
- break;
- case 'S':
- short[] sv = new short[size];
- for (i = 0; i < size; i++) {
- sv[i] = (short) readInt(items[readUnsignedShort(v)]);
- v += 3;
- }
- av.visit(name, sv);
- --v;
- break;
- case 'C':
- char[] cv = new char[size];
- for (i = 0; i < size; i++) {
- cv[i] = (char) readInt(items[readUnsignedShort(v)]);
- v += 3;
- }
- av.visit(name, cv);
- --v;
- break;
- case 'I':
- int[] iv = new int[size];
- for (i = 0; i < size; i++) {
- iv[i] = readInt(items[readUnsignedShort(v)]);
- v += 3;
- }
- av.visit(name, iv);
- --v;
- break;
- case 'J':
- long[] lv = new long[size];
- for (i = 0; i < size; i++) {
- lv[i] = readLong(items[readUnsignedShort(v)]);
- v += 3;
- }
- av.visit(name, lv);
- --v;
- break;
- case 'F':
- float[] fv = new float[size];
- for (i = 0; i < size; i++) {
- fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));
- v += 3;
- }
- av.visit(name, fv);
- --v;
- break;
- case 'D':
- double[] dv = new double[size];
- for (i = 0; i < size; i++) {
- dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));
- v += 3;
- }
- av.visit(name, dv);
- --v;
- break;
- default:
- v = readAnnotationValues(v - 3,
- buf,
- false,
- av.visitArray(name));
- }
- }
- return v;
- }
+ switch (this.b[v++] & 0xFF)
+ {
+ case 'B' :
+ byte[] bv = new byte[size];
+ for (i = 0; i < size; i++)
+ {
+ bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, bv);
+ --v;
+ break;
+ case 'Z' :
+ boolean[] zv = new boolean[size];
+ for (i = 0; i < size; i++)
+ {
+ zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
+ v += 3;
+ }
+ av.visit(name, zv);
+ --v;
+ break;
+ case 'S' :
+ short[] sv = new short[size];
+ for (i = 0; i < size; i++)
+ {
+ sv[i] = (short) readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, sv);
+ --v;
+ break;
+ case 'C' :
+ char[] cv = new char[size];
+ for (i = 0; i < size; i++)
+ {
+ cv[i] = (char) readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, cv);
+ --v;
+ break;
+ case 'I' :
+ int[] iv = new int[size];
+ for (i = 0; i < size; i++)
+ {
+ iv[i] = readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, iv);
+ --v;
+ break;
+ case 'J' :
+ long[] lv = new long[size];
+ for (i = 0; i < size; i++)
+ {
+ lv[i] = readLong(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, lv);
+ --v;
+ break;
+ case 'F' :
+ float[] fv = new float[size];
+ for (i = 0; i < size; i++)
+ {
+ fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));
+ v += 3;
+ }
+ av.visit(name, fv);
+ --v;
+ break;
+ case 'D' :
+ double[] dv = new double[size];
+ for (i = 0; i < size; i++)
+ {
+ dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));
+ v += 3;
+ }
+ av.visit(name, dv);
+ --v;
+ break;
+ default :
+ v = readAnnotationValues(v - 3, buf, false, av.visitArray(name));
+ }
+ }
+ return v;
+ }
- private int readFrameType(
- final Object[] frame,
- final int index,
- int v,
- final char[] buf,
- final Label[] labels)
- {
- int type = b[v++] & 0xFF;
- switch (type) {
- case 0:
- frame[index] = Opcodes.TOP;
- break;
- case 1:
- frame[index] = Opcodes.INTEGER;
- break;
- case 2:
- frame[index] = Opcodes.FLOAT;
- break;
- case 3:
- frame[index] = Opcodes.DOUBLE;
- break;
- case 4:
- frame[index] = Opcodes.LONG;
- break;
- case 5:
- frame[index] = Opcodes.NULL;
- break;
- case 6:
- frame[index] = Opcodes.UNINITIALIZED_THIS;
- break;
- case 7: // Object
- frame[index] = readClass(v, buf);
- v += 2;
- break;
- default: // Uninitialized
- frame[index] = readLabel(readUnsignedShort(v), labels);
- v += 2;
- }
- return v;
- }
+ private int readFrameType(final Object[] frame, final int index, int v, final char[] buf, final Label[] labels)
+ {
+ int type = b[v++] & 0xFF;
+ switch (type)
+ {
+ case 0 :
+ frame[index] = Opcodes.TOP;
+ break;
+ case 1 :
+ frame[index] = Opcodes.INTEGER;
+ break;
+ case 2 :
+ frame[index] = Opcodes.FLOAT;
+ break;
+ case 3 :
+ frame[index] = Opcodes.DOUBLE;
+ break;
+ case 4 :
+ frame[index] = Opcodes.LONG;
+ break;
+ case 5 :
+ frame[index] = Opcodes.NULL;
+ break;
+ case 6 :
+ frame[index] = Opcodes.UNINITIALIZED_THIS;
+ break;
+ case 7 : // Object
+ frame[index] = readClass(v, buf);
+ v += 2;
+ break;
+ default : // Uninitialized
+ frame[index] = readLabel(readUnsignedShort(v), labels);
+ v += 2;
+ }
+ return v;
+ }
- /**
- * Returns the label corresponding to the given offset. The default
- * implementation of this method creates a label for the given offset if it
- * has not been already created.
- *
- * @param offset a bytecode offset in a method.
- * @param labels the already created labels, indexed by their offset. If a
- * label already exists for offset this method must not create a new
- * one. Otherwise it must store the new label in this array.
- * @return a non null Label, which must be equal to labels[offset].
- */
- protected Label readLabel(int offset, Label[] labels) {
- if (labels[offset] == null) {
- labels[offset] = new Label();
- }
- return labels[offset];
- }
+ /**
+ * Returns the label corresponding to the given offset. The default
+ * implementation of this method creates a label for the given offset if it
+ * has not been already created.
+ *
+ * @param offset a bytecode offset in a method.
+ * @param labels the already created labels, indexed by their offset. If a
+ * label already exists for offset this method must not create a new
+ * one. Otherwise it must store the new label in this array.
+ * @return a non null Label, which must be equal to labels[offset].
+ */
+ protected Label readLabel(int offset, Label[] labels)
+ {
+ if (labels[offset] == null)
+ {
+ labels[offset] = new Label();
+ }
+ return labels[offset];
+ }
- /**
- * Reads an attribute in {@link #b b}.
- *
- * @param attrs prototypes of the attributes that must be parsed during the
- * visit of the class. Any attribute whose type is not equal to the
- * type of one the prototypes is ignored (i.e. an empty
- * {@link Attribute} instance is returned).
- * @param type the type of the attribute.
- * @param off index of the first byte of the attribute's content in
- * {@link #b b}. The 6 attribute header bytes, containing the type
- * and the length of the attribute, are not taken into account here
- * (they have already been read).
- * @param len the length of the attribute's content.
- * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
- * {@link #readClass(int,char[]) readClass} or
- * {@link #readConst readConst}.
- * @param codeOff index of the first byte of code's attribute content in
- * {@link #b b}, or -1 if the attribute to be read is not a code
- * attribute. The 6 attribute header bytes, containing the type and
- * the length of the attribute, are not taken into account here.
- * @param labels the labels of the method's code, or <tt>null</tt> if the
- * attribute to be read is not a code attribute.
- * @return the attribute that has been read, or <tt>null</tt> to skip this
- * attribute.
- */
- private Attribute readAttribute(
- final Attribute[] attrs,
- final String type,
- final int off,
- final int len,
- final char[] buf,
- final int codeOff,
- final Label[] labels)
- {
- for (int i = 0; i < attrs.length; ++i) {
- if (attrs[i].type.equals(type)) {
- return attrs[i].read(this, off, len, buf, codeOff, labels);
- }
- }
- return new Attribute(type).read(this, off, len, null, -1, null);
- }
+ /**
+ * Reads an attribute in {@link #b b}.
+ *
+ * @param attrs prototypes of the attributes that must be parsed during the
+ * visit of the class. Any attribute whose type is not equal to the
+ * type of one the prototypes is ignored (i.e. an empty
+ * {@link Attribute} instance is returned).
+ * @param type the type of the attribute.
+ * @param off index of the first byte of the attribute's content in
+ * {@link #b b}. The 6 attribute header bytes, containing the type
+ * and the length of the attribute, are not taken into account here
+ * (they have already been read).
+ * @param len the length of the attribute's content.
+ * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or
+ * {@link #readConst readConst}.
+ * @param codeOff index of the first byte of code's attribute content in
+ * {@link #b b}, or -1 if the attribute to be read is not a code
+ * attribute. The 6 attribute header bytes, containing the type and
+ * the length of the attribute, are not taken into account here.
+ * @param labels the labels of the method's code, or <tt>null</tt> if the
+ * attribute to be read is not a code attribute.
+ * @return the attribute that has been read, or <tt>null</tt> to skip this
+ * attribute.
+ */
+ private Attribute readAttribute(final Attribute[] attrs, final String type, final int off, final int len,
+ final char[] buf, final int codeOff, final Label[] labels)
+ {
+ for (int i = 0; i < attrs.length; ++i)
+ {
+ if (attrs[i].type.equals(type))
+ {
+ return attrs[i].read(this, off, len, buf, codeOff, labels);
+ }
+ }
+ return new Attribute(type).read(this, off, len, null, -1, null);
+ }
- // ------------------------------------------------------------------------
- // Utility methods: low level parsing
- // ------------------------------------------------------------------------
+ // ------------------------------------------------------------------------
+ // Utility methods: low level parsing
+ // ------------------------------------------------------------------------
- /**
- * Returns the start index of the constant pool item in {@link #b b}, plus
- * one. <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param item the index a constant pool item.
- * @return the start index of the constant pool item in {@link #b b}, plus
- * one.
- */
- public int getItem(final int item) {
- return items[item];
- }
+ /**
+ * Returns the start index of the constant pool item in {@link #b b}, plus
+ * one. <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param item the index a constant pool item.
+ * @return the start index of the constant pool item in {@link #b b}, plus
+ * one.
+ */
+ public int getItem(final int item)
+ {
+ return items[item];
+ }
- /**
- * Reads a byte value in {@link #b b}. <i>This method is intended for
- * {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
- public int readByte(final int index) {
- return b[index] & 0xFF;
- }
+ /**
+ * Reads a byte value in {@link #b b}. <i>This method is intended for
+ * {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public int readByte(final int index)
+ {
+ return b[index] & 0xFF;
+ }
- /**
- * Reads an unsigned short value in {@link #b b}. <i>This method is
- * intended for {@link Attribute} sub classes, and is normally not needed by
- * class generators or adapters.</i>
- *
- * @param index the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
- public int readUnsignedShort(final int index) {
- byte[] b = this.b;
- return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
- }
+ /**
+ * Reads an unsigned short value in {@link #b b}. <i>This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public int readUnsignedShort(final int index)
+ {
+ byte[] b = this.b;
+ return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
+ }
- /**
- * Reads a signed short value in {@link #b b}. <i>This method is intended
- * for {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
- public short readShort(final int index) {
- byte[] b = this.b;
- return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
- }
+ /**
+ * Reads a signed short value in {@link #b b}. <i>This method is intended
+ * for {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public short readShort(final int index)
+ {
+ byte[] b = this.b;
+ return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
+ }
- /**
- * Reads a signed int value in {@link #b b}. <i>This method is intended for
- * {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
- public int readInt(final int index) {
- byte[] b = this.b;
- return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
- | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
- }
+ /**
+ * Reads a signed int value in {@link #b b}. <i>This method is intended for
+ * {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public int readInt(final int index)
+ {
+ byte[] b = this.b;
+ return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) | ((b[index + 2] & 0xFF) << 8)
+ | (b[index + 3] & 0xFF);
+ }
- /**
- * Reads a signed long value in {@link #b b}. <i>This method is intended
- * for {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
- public long readLong(final int index) {
- long l1 = readInt(index);
- long l0 = readInt(index + 4) & 0xFFFFFFFFL;
- return (l1 << 32) | l0;
- }
+ /**
+ * Reads a signed long value in {@link #b b}. <i>This method is intended
+ * for {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public long readLong(final int index)
+ {
+ long l1 = readInt(index);
+ long l0 = readInt(index + 4) & 0xFFFFFFFFL;
+ return (l1 << 32) | l0;
+ }
- /**
- * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
- * is intended for {@link Attribute} sub classes, and is normally not needed
- * by class generators or adapters.</i>
- *
- * @param index the start index of an unsigned short value in {@link #b b},
- * whose value is the index of an UTF8 constant pool item.
- * @param buf buffer to be used to read the item. This buffer must be
- * sufficiently large. It is not automatically resized.
- * @return the String corresponding to the specified UTF8 item.
- */
- public String readUTF8(int index, final char[] buf) {
- int item = readUnsignedShort(index);
- String s = strings[item];
- if (s != null) {
- return s;
- }
- index = items[item];
- return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
- }
+ /**
+ * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
+ * is intended for {@link Attribute} sub classes, and is normally not needed
+ * by class generators or adapters.</i>
+ *
+ * @param index the start index of an unsigned short value in {@link #b b},
+ * whose value is the index of an UTF8 constant pool item.
+ * @param buf buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified UTF8 item.
+ */
+ public String readUTF8(int index, final char[] buf)
+ {
+ int item = readUnsignedShort(index);
+ String s = strings[item];
+ if (s != null)
+ {
+ return s;
+ }
+ index = items[item];
+ return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
+ }
- /**
- * Reads UTF8 string in {@link #b b}.
- *
- * @param index start offset of the UTF8 string to be read.
- * @param utfLen length of the UTF8 string to be read.
- * @param buf buffer to be used to read the string. This buffer must be
- * sufficiently large. It is not automatically resized.
- * @return the String corresponding to the specified UTF8 string.
- */
- private String readUTF(int index, final int utfLen, final char[] buf) {
- int endIndex = index + utfLen;
- byte[] b = this.b;
- int strLen = 0;
- int c;
- int st = 0;
- char cc = 0;
- while (index < endIndex) {
- c = b[index++];
- switch (st) {
- case 0:
- c = c & 0xFF;
- if (c < 0x80) { // 0xxxxxxx
- buf[strLen++] = (char) c;
- } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx
- cc = (char) (c & 0x1F);
- st = 1;
- } else { // 1110 xxxx 10xx xxxx 10xx xxxx
- cc = (char) (c & 0x0F);
- st = 2;
- }
- break;
-
- case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char
- buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
- st = 0;
- break;
-
- case 2: // byte 2 of 3-byte char
- cc = (char) ((cc << 6) | (c & 0x3F));
- st = 1;
- break;
- }
- }
- return new String(buf, 0, strLen);
- }
-
- /**
- * Reads a class constant pool item in {@link #b b}. <i>This method is
- * intended for {@link Attribute} sub classes, and is normally not needed by
- * class generators or adapters.</i>
- *
- * @param index the start index of an unsigned short value in {@link #b b},
- * whose value is the index of a class constant pool item.
- * @param buf buffer to be used to read the item. This buffer must be
- * sufficiently large. It is not automatically resized.
- * @return the String corresponding to the specified class item.
- */
- public String readClass(final int index, final char[] buf) {
- // computes the start index of the CONSTANT_Class item in b
- // and reads the CONSTANT_Utf8 item designated by
- // the first two bytes of this CONSTANT_Class item
- return readUTF8(items[readUnsignedShort(index)], buf);
- }
+ /**
+ * Reads UTF8 string in {@link #b b}.
+ *
+ * @param index start offset of the UTF8 string to be read.
+ * @param utfLen length of the UTF8 string to be read.
+ * @param buf buffer to be used to read the string. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified UTF8 string.
+ */
+ private String readUTF(int index, final int utfLen, final char[] buf)
+ {
+ int endIndex = index + utfLen;
+ byte[] b = this.b;
+ int strLen = 0;
+ int c;
+ int st = 0;
+ char cc = 0;
+ while (index < endIndex)
+ {
+ c = b[index++];
+ switch (st)
+ {
+ case 0 :
+ c = c & 0xFF;
+ if (c < 0x80)
+ { // 0xxxxxxx
+ buf[strLen++] = (char) c;
+ }
+ else if (c < 0xE0 && c > 0xBF)
+ { // 110x xxxx 10xx xxxx
+ cc = (char) (c & 0x1F);
+ st = 1;
+ }
+ else
+ { // 1110 xxxx 10xx xxxx 10xx xxxx
+ cc = (char) (c & 0x0F);
+ st = 2;
+ }
+ break;
- /**
- * Reads a numeric or string constant pool item in {@link #b b}. <i>This
- * method is intended for {@link Attribute} sub classes, and is normally not
- * needed by class generators or adapters.</i>
- *
- * @param item the index of a constant pool item.
- * @param buf buffer to be used to read the item. This buffer must be
- * sufficiently large. It is not automatically resized.
- * @return the {@link Integer}, {@link Float}, {@link Long},
- * {@link Double}, {@link String} or {@link Type} corresponding to
- * the given constant pool item.
- */
- public Object readConst(final int item, final char[] buf) {
- int index = items[item];
- switch (b[index - 1]) {
- case ClassWriter.INT:
- return new Integer(readInt(index));
- case ClassWriter.FLOAT:
- return new Float(Float.intBitsToFloat(readInt(index)));
- case ClassWriter.LONG:
- return new Long(readLong(index));
- case ClassWriter.DOUBLE:
- return new Double(Double.longBitsToDouble(readLong(index)));
- case ClassWriter.CLASS:
- return Type.getObjectType(readUTF8(index, buf));
- // case ClassWriter.STR:
- default:
- return readUTF8(index, buf);
- }
- }
+ case 1 : // byte 2 of 2-byte char or byte 3 of 3-byte char
+ buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
+ st = 0;
+ break;
+
+ case 2 : // byte 2 of 3-byte char
+ cc = (char) ((cc << 6) | (c & 0x3F));
+ st = 1;
+ break;
+ }
+ }
+ return new String(buf, 0, strLen);
+ }
+
+ /**
+ * Reads a class constant pool item in {@link #b b}. <i>This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.</i>
+ *
+ * @param index the start index of an unsigned short value in {@link #b b},
+ * whose value is the index of a class constant pool item.
+ * @param buf buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified class item.
+ */
+ public String readClass(final int index, final char[] buf)
+ {
+ // computes the start index of the CONSTANT_Class item in b
+ // and reads the CONSTANT_Utf8 item designated by
+ // the first two bytes of this CONSTANT_Class item
+ return readUTF8(items[readUnsignedShort(index)], buf);
+ }
+
+ /**
+ * Reads a numeric or string constant pool item in {@link #b b}. <i>This
+ * method is intended for {@link Attribute} sub classes, and is normally not
+ * needed by class generators or adapters.</i>
+ *
+ * @param item the index of a constant pool item.
+ * @param buf buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double}, {@link String} or {@link Type} corresponding to
+ * the given constant pool item.
+ */
+ public Object readConst(final int item, final char[] buf)
+ {
+ int index = items[item];
+ switch (b[index - 1])
+ {
+ case ClassWriter.INT :
+ return new Integer(readInt(index));
+ case ClassWriter.FLOAT :
+ return new Float(Float.intBitsToFloat(readInt(index)));
+ case ClassWriter.LONG :
+ return new Long(readLong(index));
+ case ClassWriter.DOUBLE :
+ return new Double(Double.longBitsToDouble(readLong(index)));
+ case ClassWriter.CLASS :
+ return Type.getObjectType(readUTF8(index, buf));
+ // case ClassWriter.STR:
+ default :
+ return readUTF8(index, buf);
+ }
+ }
}
More information about the jboss-cvs-commits
mailing list