Class CodeAttributeEditor

java.lang.Object
proguard.classfile.editor.CodeAttributeEditor
All Implemented Interfaces:
LocalVariableTargetElementVisitor, TargetInfoVisitor, TypeAnnotationVisitor, StackMapFrameVisitor, VerificationTypeVisitor, AttributeVisitor, ExceptionInfoVisitor, LineNumberInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, InstructionVisitor

This AttributeVisitor accumulates specified changes to code, and then applies these accumulated changes to the code attributes that it visits.

The class also supports labels (label()) and exception handlers (catch_(int,int,int)) in replacement sequences. They provide local branch offsets inside the replacement sequences (CodeAttributeEditor.Label.offset()). For example, replacing a specified instruction in a method by a sequence of instructions, with the help of InstructionSequenceBuilder:

     Clazz         clazz         = ...
     Method        method        = ...
     CodeAttribute codeAttribute = ...
     int           offset        = ...

     CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();

     InstructionSequenceBuilder builder =
         new InstructionSequenceBuilder(clazz);

     // Create labels and instructions.
     final CodeAttributeEditor.Label TRY_START = codeAttributeEditor.label();
     final CodeAttributeEditor.Label TRY_END   = codeAttributeEditor.label();
     final CodeAttributeEditor.Label CATCH_END = codeAttributeEditor.label();

     final CodeAttributeEditor.Label CATCH_EXCEPTION =
         codeAttributeEditor.catch_(TRY_START.offset(),
                                    TRY_END.offset(),
                                    constantPoolEditor.addClassConstant("java/lang/Exception", null));

     Instructions[] replacementInstructions = builder
         .label(TRY_START)
         ......
         .label(TRY_END)
         .goto_(CATCH_END.offset())
         .catch_(CATCH_EXCEPTION)
         ......
         .athrow()
         .label(CATCH_END)
         ......
         .instructions();

     // Prepare the editor for this code.
     codeAttributeEditor.reset(codeAttribute.u4codeLength);

     // Edit the code -- in this case, replace an instruction.
     codeAttributeEditor.replaceInstruction(offset, replacementInstructions);

     // Apply the changes.
     codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
 
  • Field Details

    • RESTORE_PREVIOUS_LINE_NUMBER

      public static final int RESTORE_PREVIOUS_LINE_NUMBER
      Magic line number that indicates the previous line number should be restored. The restored line number is the first preceding line number with a different source.
      See Also:
    • preOffsetInsertions

      public Instruction[] preOffsetInsertions
    • preInsertions

      public Instruction[] preInsertions
    • replacements

      public Instruction[] replacements
    • postInsertions

      public Instruction[] postInsertions
    • deleted

      public boolean[] deleted
  • Constructor Details

    • CodeAttributeEditor

      public CodeAttributeEditor()
      Creates a new CodeAttributeEditor that automatically updates frame sizes and shrinks instructions.
    • CodeAttributeEditor

      public CodeAttributeEditor(boolean updateFrameSizes, boolean shrinkInstructions)
      Creates a new CodeAttributeEditor.
      Parameters:
      updateFrameSizes - specifies whether frame sizes of edited code should be updated.
      shrinkInstructions - specifies whether added instructions should automatically be shrunk before being written.
  • Method Details