Package org.objectweb.asm.tree

Provides an ASM visitor that constructs a tree representation of the classes it visits.

See:
          Description

Class Summary
AbstractInsnNode A node that represents a bytecode instruction.
AnnotationNode A node that represents an annotationn.
ClassNode A node that represents a class.
FieldInsnNode A node that represents a field instruction.
FieldNode A node that represents a field.
IincInsnNode A node that represents an IINC instruction.
InnerClassNode A node that represents an inner class.
InsnNode A node that represents a zero operand instruction.
IntInsnNode A node that represents an instruction with a single int operand.
JumpInsnNode A node that represents a jump instruction.
LabelNode An AbstractInsnNode that encapsulates a Label.
LdcInsnNode A node that represents an LDC instruction.
LineNumberNode A node that represents a line number declaration.
LocalVariableNode A node that represents a local variable declaration.
LookupSwitchInsnNode A node that represents a LOOKUPSWITCH instruction.
MemberNode An abstract class, field or method node.
MethodInsnNode A node that represents a method instruction.
MethodNode A node that represents a method.
MultiANewArrayInsnNode A node that represents a MULTIANEWARRAY instruction.
TableSwitchInsnNode A node that represents a TABLESWITCH instruction.
TryCatchBlockNode A node that represents a try catch block.
TypeInsnNode A node that represents a type instruction.
VarInsnNode A node that represents a local variable instruction.
 

Package org.objectweb.asm.tree Description

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).

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 asm-tree.jar library that is separated from (but requires) the asm.jar library, which contains the core ASM framework. This is also why it is recommanded not to use this class adapter when it is possible.

The root class is the ClassNode, that can be created from scratch or from existing bytecode. For example:

  ClassReader cr = new ClassReader(source);
  ClassNode cn = new ClassNode();
  cr.accept(cn, true);

Now content of ClassNode can be modified and then serialized back into bytecode:

  ClassWriter cw = new ClassWriter(true);
  cn.accept(cw);

Several strategies can be used to construct method code from scratch. The first possibility is to create a MethodNode, and then create and add XXXInsnNode to the instructions list:

MethodNode m = new MethodNode(...);
m.instructions.add(new VarInsnNode(ALOAD, 0));
...

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:

MethodNode m = new MethodNode(...);
m.visitVarInsn(ALOAD, 0);
...

If you cannot generate all the instructions in sequential order, i.e. if you need to keep some pointers in the instruction list to insert some instructions at these places after other instructions have been generated, you can define an InsnListInsnNode pseudo instruction class that will in fact contain an instruction list, will possibly implement the MethodVisitor interface, and whose accept method will call the accept method of all the instructions of its list.

MethodNode m = new MethodNode(...);
m.visitVarInsn(ALOAD, 0);
InsnListInsnNode ptr = new InsnListInsnNode();
m.instructions.add(ptr);
m.visitVarInsn(ALOAD, 1);
ptr.visitXXXInsn(...); // inserts an instruction between ALOAD 0 and ALOAD 1

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, and use its add method to insert instructions:

ListIterator i = m.instructions.listIterator();
while (i.hasNext()) {
    AbstractInsnNode n = (AbstractInsnNode) i.next();
    if (...) {
        i.add(new VarInsnNode(ALOAD, 0));
    }
}

If you want to insert these instructions through the MethodVisitor interface, you can define your own InsnListIterator class, that will implement both the ListIterator and MethodVisitor interface.

Another strategy is to use ListIterator.add to insert InsnListInsnNode pseudo instructions, and then use these inserted pseudo instructions to insert an arbitrary number of instructions at these places.

Since:
ASM 1.3.3