[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