<html>
<!--
 * ASM: a very small and fast Java bytecode manipulation framework
 * Copyright (c) 2000-2005 INRIA, France Telecom
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
-->
<body>
  
<p>  
Provides an ASM visitor that constructs a tree representation of the
classes it visits. This class adapter can be useful to implement "complex"
class manipulation operations, i.e., operations that would be very hard to
implement without using a tree representation (such as optimizing the number
of local variables used by a method).
</p>
  
<p>
However, this class adapter has a cost: it makes ASM bigger and slower. Indeed
it requires more than twenty new classes, and multiplies the time needed to
transform a class by almost two (it is almost two times faster to read, "modify"
and write a class with a ClassAdapter than with a ClassNode). This is why
this package is bundled in an optional <tt>asm-tree.jar</tt> library that
is separated from (but requires) the <tt>asm.jar</tt> library, which contains
the core ASM framework. This is also why <i><font color="red">it is recommended
not to use this class adapter when it is possible</font></i>.
</p>

<p>
The root class is the ClassNode, that can be created from existing bytecode. For example:
</p>
  
<pre>
  ClassReader cr = new ClassReader(source);
  ClassNode cn = new ClassNode();
  cr.accept(cn, true);
</pre>

<p>
Now content of ClassNode can be modified and then
serialized back into bytecode:
</p>

<pre>
  ClassWriter cw = new ClassWriter(true);
  cn.accept(cw);
</pre>  

<p>
Using simple ClassAdapter it is possible to create MethodNode instances per-method.
In this example MethodNode is acting as a buffer that is flushed out at visitEnd() call:
</p>

<pre>
  ClassReader cr = new ClassReader(source);
  ClassWriter cw = new ClassWriter();
  ClassAdapter ca = new ClassAdapter(cw) {
      public MethodVisitor visitMethod(int access, String name, 
          String desc, String signature, String[] exceptions) {
        final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
        MethodNode mn = new MethodNode(access, name, desc, signature, exceptions) {
            public void visitEnd() {
              // transform or analyze method code using tree API
              accept(mv);
            }
          };
      }
    };
  cr.accept(ca, true);
</pre>

<p>  
Several strategies can be used to construct method code from scratch. The first
option is to create a MethodNode, and then create XXXInsnNode instances and 
add them to the instructions list:
</p>

<pre>
MethodNode m = new MethodNode(...);
m.instructions.add(new VarInsnNode(ALOAD, 0));
...
</pre>

<p>
Alternatively, you can use the fact that MethodNode is a MethodVisitor, and use
that to create the XXXInsnNode and add them to the instructions list through
the standard MethodVisitor interface:
</p>

<pre>
MethodNode m = new MethodNode(...);
m.visitVarInsn(ALOAD, 0);
...
</pre>

<p>
If you cannot generate all the instructions in sequential order, i.e. if you 
need to save some pointer in the instruction list and then insert instructions
at that place after other instructions have been generated, you can use InsnList 
methods insert() and insertBefore() to insert instructions at saved pointer.
</p>

<pre>
MethodNode m = new MethodNode(...);
m.visitVarInsn(ALOAD, 0);
AbstractInsnNode ptr = m.instructions.getLast();
m.visitVarInsn(ALOAD, 1);
// inserts an instruction between ALOAD 0 and ALOAD 1
m.instructions.insert(ptr, new VarInsnNode(ALOAD, 0));
...
</pre>

<p>
If you need to insert instructions while iterating over an existing instruction 
list, you can also use several strategies. The first one is to use a 
ListIterator over the instruction list:
</p>

<pre>
ListIterator it = m.instructions.iterator();
while (it.hasNext()) {
    AbstractInsnNode n = (AbstractInsnNode) it.next();
    if (...) {
        it.add(new VarInsnNode(ALOAD, 0));
    }
}
</pre>

<p>
It is also possible to convert instruction list into the array and iterate trough
array elements:
</p>

<pre>
AbstractInsnNode[] insns = m.instructions.toArray();
for(int i = 0; i&lt;insns.length; i++) {
    AbstractInsnNode n = insns[i];
    if (...) {
        m.instructions.insert(n, new VarInsnNode(ALOAD, 0));
    }
}
</pre>

<p>
If you want to insert these instructions through the MethodVisitor interface,
you can use another instance of MethodNode as a MethodVisitor and then 
insert instructions collected by that instance into the instruction list. 
For example:
</p>

<pre>
AbstractInsnNode[] insns = m.instructions.toArray();
for(int i = 0; i&lt;insns.length; i++) {
    AbstractInsnNode n = insns[i];
    if (...) {
        MethodNode mn = new MethodNode();
        mn.visitVarInsn(ALOAD, 0);
        mn.visitVarInsn(ALOAD, 1);
        m.instructions.insert(n, mn.instructions);
    }
}
</pre>

<p>  
@since ASM 1.3.3
</p>
    
</body>
</html>
