Class CodeIterator

java.lang.Object
javassist.bytecode.CodeIterator
All Implemented Interfaces:
Opcode

public class CodeIterator extends Object implements Opcode
An iterator for editing a code attribute.

To directly read or edit a bytecode sequence, call byteAt(int), s16bitAt(int), writeByte(int, int), write16bit(int, int), and other methods. For example, if method refers to a CtMethod object, the following code substitutes the NOP instruction for the first instruction of the method:

 CodeAttribute ca = method.getMethodInfo().getCodeAttribute();
 CodeIterator ci = ca.iterator();
 ci.writeByte(Opcode.NOP, 0);

To visit every instruction, call next() on a CodeIterator. It returns the index of the first byte of the next instruction.

If there are multiple CodeIterators referring to the same Code_attribute, then inserting a gap by one CodeIterator will break the other CodeIterator.

This iterator does not provide remove(). If a piece of code in a Code_attribute is unnecessary, it should be overwritten with NOP.

See Also:
  • Method Details

    • begin

      public void begin()
      Moves to the first instruction.
    • move

      public void move(int index)
      Moves to the given index.

      The index of the next instruction is set to the given index. The successive call to next() returns the index that has been given to move().

      Note that the index is into the byte array returned by get().getCode().

      See Also:
    • setMark

      public void setMark(int index)
      Sets a mark to the bytecode at the given index. The mark can be used to track the position of that bytecode when code blocks are inserted. If a code block is inclusively inserted at the position of the bytecode, the mark is set to the inserted code block.
      Since:
      3.11
      See Also:
    • setMark2

      public void setMark2(int index)
      Sets a mark to the bytecode at the given index. The mark can be used to track the position of that bytecode when code blocks are inserted. If a code block is inclusively inserted at the position of the bytecode, the mark is set to the inserted code block.
      Since:
      3.26
      See Also:
    • getMark

      public int getMark()
      Gets the index of the position of the mark set by setMark.
      Returns:
      the index of the position.
      Since:
      3.11
      See Also:
    • getMark2

      public int getMark2()
      Gets the index of the position of the mark set by setMark2.
      Returns:
      the index of the position.
      Since:
      3.26
      See Also:
    • get

      public CodeAttribute get()
      Returns a Code attribute read with this iterator.
    • getCodeLength

      public int getCodeLength()
      Returns code_length of Code_attribute.
    • byteAt

      public int byteAt(int index)
      Returns the unsigned 8bit value at the given index.
    • signedByteAt

      public int signedByteAt(int index)
      Returns the signed 8bit value at the given index.
    • writeByte

      public void writeByte(int value, int index)
      Writes an 8bit value at the given index.
    • u16bitAt

      public int u16bitAt(int index)
      Returns the unsigned 16bit value at the given index.
    • s16bitAt

      public int s16bitAt(int index)
      Returns the signed 16bit value at the given index.
    • write16bit

      public void write16bit(int value, int index)
      Writes a 16 bit integer at the index.
    • s32bitAt

      public int s32bitAt(int index)
      Returns the signed 32bit value at the given index.
    • write32bit

      public void write32bit(int value, int index)
      Writes a 32bit integer at the index.
    • write

      public void write(byte[] code, int index)
      Writes a byte array at the index.
      Parameters:
      code - may be a zero-length array.
    • hasNext

      public boolean hasNext()
      Returns true if there is more instructions.
    • next

      public int next() throws BadBytecode
      Returns the index of the next instruction (not the operand following the current opcode).

      Note that the index is into the byte array returned by get().getCode().

      Throws:
      BadBytecode
      See Also:
    • lookAhead

      public int lookAhead()
      Obtains the value that the next call to next() will return.

      This method is side-effects free. Successive calls to lookAhead() return the same value until next() is called.

    • skipConstructor

      public int skipConstructor() throws BadBytecode
      Moves to the instruction for either super() or this().

      This method skips all the instructions for computing arguments to super() or this(), which should be placed at the beginning of a constructor body.

      This method returns the index of INVOKESPECIAL instruction executing super() or this(). A successive call to next() returns the index of the next instruction following that INVOKESPECIAL.

      This method works only for a constructor.

      Returns:
      the index of the INVOKESPECIAL instruction, or -1 if a constructor invocation is not found.
      Throws:
      BadBytecode
    • skipSuperConstructor

      public int skipSuperConstructor() throws BadBytecode
      Moves to the instruction for super().

      This method skips all the instructions for computing arguments to super(), which should be placed at the beginning of a constructor body.

      This method returns the index of INVOKESPECIAL instruction executing super(). A successive call to next() returns the index of the next instruction following that INVOKESPECIAL.

      This method works only for a constructor.

      Returns:
      the index of the INVOKESPECIAL instruction, or -1 if a super constructor invocation is not found but this() is found.
      Throws:
      BadBytecode
    • skipThisConstructor

      public int skipThisConstructor() throws BadBytecode
      Moves to the instruction for this().

      This method skips all the instructions for computing arguments to this(), which should be placed at the beginning of a constructor body.

      This method returns the index of INVOKESPECIAL instruction executing this(). A successive call to next() returns the index of the next instruction following that INVOKESPECIAL.

      This method works only for a constructor.

      Returns:
      the index of the INVOKESPECIAL instruction, or -1 if a explicit constructor invocation is not found but super() is found.
      Throws:
      BadBytecode
    • insert

      public int insert(byte[] code) throws BadBytecode
      Inserts the given bytecode sequence before the next instruction that would be returned by next() (not before the instruction returned by the last call to next()). Branch offsets and the exception table are also updated.

      If the next instruction is at the beginning of a block statement, then the bytecode is inserted within that block.

      An extra gap may be inserted at the end of the inserted bytecode sequence for adjusting alignment if the code attribute includes LOOKUPSWITCH or TABLESWITCH.

      Parameters:
      code - inserted bytecode sequence.
      Returns:
      the index indicating the first byte of the inserted byte sequence.
      Throws:
      BadBytecode
    • insert

      public void insert(int pos, byte[] code) throws BadBytecode
      Inserts the given bytecode sequence before the instruction at the given index pos. Branch offsets and the exception table are also updated.

      If the instruction at the given index is at the beginning of a block statement, then the bytecode is inserted within that block.

      An extra gap may be inserted at the end of the inserted bytecode sequence for adjusting alignment if the code attribute includes LOOKUPSWITCH or TABLESWITCH.

      The index at which the byte sequence is actually inserted might be different from pos since some other bytes might be inserted at other positions (e.g. to change GOTO to GOTO_W).

      Parameters:
      pos - the index at which a byte sequence is inserted.
      code - inserted bytecode sequence.
      Throws:
      BadBytecode
    • insertAt

      public int insertAt(int pos, byte[] code) throws BadBytecode
      Inserts the given bytecode sequence before the instruction at the given index pos. Branch offsets and the exception table are also updated.

      If the instruction at the given index is at the beginning of a block statement, then the bytecode is inserted within that block.

      An extra gap may be inserted at the end of the inserted bytecode sequence for adjusting alignment if the code attribute includes LOOKUPSWITCH or TABLESWITCH.

      Parameters:
      pos - the index at which a byte sequence is inserted.
      code - inserted bytecode sequence.
      Returns:
      the index indicating the first byte of the inserted byte sequence, which might be different from pos.
      Throws:
      BadBytecode
      Since:
      3.11
    • insertEx

      public int insertEx(byte[] code) throws BadBytecode
      Inserts the given bytecode sequence exclusively before the next instruction that would be returned by next() (not before the instruction returned by tha last call to next()). Branch offsets and the exception table are also updated.

      If the next instruction is at the beginning of a block statement, then the bytecode is excluded from that block.

      An extra gap may be inserted at the end of the inserted bytecode sequence for adjusting alignment if the code attribute includes LOOKUPSWITCH or TABLESWITCH.

      Parameters:
      code - inserted bytecode sequence.
      Returns:
      the index indicating the first byte of the inserted byte sequence.
      Throws:
      BadBytecode
    • insertEx

      public void insertEx(int pos, byte[] code) throws BadBytecode
      Inserts the given bytecode sequence exclusively before the instruction at the given index pos. Branch offsets and the exception table are also updated.

      If the instruction at the given index is at the beginning of a block statement, then the bytecode is excluded from that block.

      An extra gap may be inserted at the end of the inserted bytecode sequence for adjusting alignment if the code attribute includes LOOKUPSWITCH or TABLESWITCH.

      The index at which the byte sequence is actually inserted might be different from pos since some other bytes might be inserted at other positions (e.g. to change GOTO to GOTO_W).

      Parameters:
      pos - the index at which a byte sequence is inserted.
      code - inserted bytecode sequence.
      Throws:
      BadBytecode
    • insertExAt

      public int insertExAt(int pos, byte[] code) throws BadBytecode
      Inserts the given bytecode sequence exclusively before the instruction at the given index pos. Branch offsets and the exception table are also updated.

      If the instruction at the given index is at the beginning of a block statement, then the bytecode is excluded from that block.

      An extra gap may be inserted at the end of the inserted bytecode sequence for adjusting alignment if the code attribute includes LOOKUPSWITCH or TABLESWITCH.

      Parameters:
      pos - the index at which a byte sequence is inserted.
      code - inserted bytecode sequence.
      Returns:
      the index indicating the first byte of the inserted byte sequence, which might be different from pos.
      Throws:
      BadBytecode
      Since:
      3.11
    • insertGap

      public int insertGap(int length) throws BadBytecode
      Inserts a gap before the next instruction that would be returned by next() (not before the instruction returned by the last call to next()). Branch offsets and the exception table are also updated. The inserted gap is filled with NOP. The gap length may be extended to a multiple of 4.

      If the next instruction is at the beginning of a block statement, then the gap is inserted within that block.

      Parameters:
      length - gap length
      Returns:
      the index indicating the first byte of the inserted gap.
      Throws:
      BadBytecode
    • insertGap

      public int insertGap(int pos, int length) throws BadBytecode
      Inserts a gap in front of the instruction at the given index pos. Branch offsets and the exception table are also updated. The inserted gap is filled with NOP. The gap length may be extended to a multiple of 4.

      If the instruction at the given index is at the beginning of a block statement, then the gap is inserted within that block.

      Parameters:
      pos - the index at which a gap is inserted.
      length - gap length.
      Returns:
      the length of the inserted gap. It might be bigger than length.
      Throws:
      BadBytecode
    • insertExGap

      public int insertExGap(int length) throws BadBytecode
      Inserts an exclusive gap before the next instruction that would be returned by next() (not before the instruction returned by the last call to next()). Branch offsets and the exception table are also updated. The inserted gap is filled with NOP. The gap length may be extended to a multiple of 4.

      If the next instruction is at the beginning of a block statement, then the gap is excluded from that block.

      Parameters:
      length - gap length
      Returns:
      the index indicating the first byte of the inserted gap.
      Throws:
      BadBytecode
    • insertExGap

      public int insertExGap(int pos, int length) throws BadBytecode
      Inserts an exclusive gap in front of the instruction at the given index pos. Branch offsets and the exception table are also updated. The inserted gap is filled with NOP. The gap length may be extended to a multiple of 4.

      If the instruction at the given index is at the beginning of a block statement, then the gap is excluded from that block.

      Parameters:
      pos - the index at which a gap is inserted.
      length - gap length.
      Returns:
      the length of the inserted gap. It might be bigger than length.
      Throws:
      BadBytecode
    • insertGapAt

      public CodeIterator.Gap insertGapAt(int pos, int length, boolean exclusive) throws BadBytecode
      Inserts an inclusive or exclusive gap in front of the instruction at the given index pos. Branch offsets and the exception table in the method body are also updated. The inserted gap is filled with NOP. The gap length may be extended to a multiple of 4.

      Suppose that the instruction at the given index is at the beginning of a block statement. If the gap is inclusive, then it is included within that block. If the gap is exclusive, then it is excluded from that block.

      The index at which the gap is actually inserted might be different from pos since some other bytes might be inserted at other positions (e.g. to change GOTO to GOTO_W). The index is available from the Gap object returned by this method.

      Suppose that the gap is inserted at the position of the next instruction that would be returned by next() (not the last instruction returned by the last call to next()). The next instruction returned by next() after the gap is inserted is still the same instruction. It is not NOP at the first byte of the inserted gap.

      Parameters:
      pos - the index at which a gap is inserted.
      length - gap length.
      exclusive - true if exclusive, otherwise false.
      Returns:
      the position and the length of the inserted gap.
      Throws:
      BadBytecode
      Since:
      3.11
    • insert

      public void insert(ExceptionTable et, int offset)
      Copies and inserts the entries in the given exception table at the beginning of the exception table in the code attribute edited by this object.
      Parameters:
      offset - the value added to the code positions included in the entries.
    • append

      public int append(byte[] code)
      Appends the given bytecode sequence at the end.
      Parameters:
      code - the bytecode appended.
      Returns:
      the position of the first byte of the appended bytecode.
    • appendGap

      public void appendGap(int gapLength)
      Appends a gap at the end of the bytecode sequence.
      Parameters:
      gapLength - gap length
    • append

      public void append(ExceptionTable et, int offset)
      Copies and appends the entries in the given exception table at the end of the exception table in the code attribute edited by this object.
      Parameters:
      offset - the value added to the code positions included in the entries.