public class CodeAttributeComposer extends java.lang.Object implements AttributeVisitor, InstructionVisitor, ExceptionInfoVisitor, StackMapFrameVisitor, VerificationTypeVisitor, LineNumberInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, TypeAnnotationVisitor, TargetInfoVisitor, LocalVariableTargetElementVisitor
AttributeVisitor
accumulates instructions, exceptions and line numbers, and then
adds them to a method or copies them into code attributes that it visits.
The class supports composing instructions (appendInstruction(Instruction)
), labels
(appendLabel(int)
), exception handlers (appendException(ExceptionInfo)
), and
line numbers (appendLineNumber(LineNumberInfo)
).
The labels are numeric labels that you can choose freely, for example instruction offsets from existing code that you are copying. You can then refer to them in branches and exception handlers. You can compose the code as a hierarchy of code fragments with their own local labels.
You should provide an estimated maximum size (expressed in number of bytes in the bytecode), so the implementation can efficiently allocate the necessary internal buffers without reallocating them as the code grows.
For example:
ProgramClass programClass = ... ProgramMethod programMethod = ... // Create any constants for the code. ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor(programClass); int exceptionType = constantPoolEditor.addClassConstant("java/lang/Exception", null); // Compose the code. CodeAttributeComposer composer = new CodeAttributeComposer(); final int TRY_LABEL = 0; final int IF_LABEL = 1; final int THEN_LABEL = 10; final int ELSE_LABEL = 20; final int CATCH_LABEL = 30; composer.beginCodeFragment(50); composer.appendLabel(TRY_LABEL); composer.appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_1)); composer.appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_2)); composer.appendLabel(IF_LABEL); composer.appendInstruction(new BranchInstruction(Instruction.OP_IFICMPLT, ELSE_LABEL - IF_LABEL)); composer.appendLabel(THEN_LABEL); composer.appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_1)); composer.appendInstruction(new SimpleInstruction(Instruction.OP_IRETURN)); composer.appendLabel(ELSE_LABEL); composer.appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_2)); composer.appendInstruction(new SimpleInstruction(Instruction.OP_IRETURN)); composer.appendLabel(CATCH_LABEL); composer.appendException(new ExceptionInfo(TRY_LABEL, CATCH_LABEL, CATCH_LABEL, exceptionType)); composer.appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_M1)); composer.appendInstruction(new SimpleInstruction(Instruction.OP_IRETURN)); composer.endCodeFragment(); // Add the code as a code attribute to the given method. composer.addCodeAttribute(programClass, programMethod, constantPoolEditor);
This class is mostly convenient to compose code based on existing code, where the instructions
are already available. For a more compact and readable alternative to compose code
programmatically from scratch, see CompactCodeAttributeComposer
.
If you're building many method bodies, it is more efficient to reuse a single instance of this composer for all methods that you add.
Constructor and Description |
---|
CodeAttributeComposer()
Creates a new CodeAttributeComposer that doesn't allow external branch targets or exception
offsets and that automatically shrinks instructions.
|
CodeAttributeComposer(boolean allowExternalBranchTargets,
boolean allowExternalExceptionOffsets,
boolean shrinkInstructions)
Creates a new CodeAttributeComposer.
|
CodeAttributeComposer(boolean allowExternalBranchTargets,
boolean allowExternalExceptionOffsets,
boolean shrinkInstructions,
boolean absoluteBranchOffsets)
Creates a new CodeAttributeComposer.
|
Modifier and Type | Method and Description |
---|---|
void |
addCodeAttribute(ProgramClass programClass,
ProgramMethod programMethod)
Adds the code that has been built as a code attribute to the given method.
|
void |
addCodeAttribute(ProgramClass programClass,
ProgramMethod programMethod,
ConstantPoolEditor constantPoolEditor)
Adds the code that has been built as a code attribute to the given method.
|
void |
appendException(ExceptionInfo exceptionInfo)
Appends the given exception to the exception table.
|
void |
appendInstruction(Instruction instruction)
Appends the given instruction without a defined offset.
|
void |
appendInstruction(int oldInstructionOffset,
Instruction instruction)
Appends the given instruction with the given old offset.
|
void |
appendInstructions(Instruction[] instructions)
Appends the given instruction without defined offsets.
|
void |
appendLabel(int oldInstructionOffset)
Appends the given label with the given old offset.
|
void |
appendLineNumber(LineNumberInfo lineNumberInfo)
Appends the given line number to the line number table.
|
void |
beginCodeFragment(int maximumCodeFragmentLength)
Starts a new code fragment.
|
void |
endCodeFragment()
Wraps up the current code fragment, continuing with the previous one on the stack.
|
int |
getCodeLength()
Returns the current length (in bytes) of the code attribute being composed.
|
int |
insertLineNumber(int minimumIndex,
LineNumberInfo lineNumberInfo)
Inserts the given line number at the appropriate position in the line number table.
|
int |
insertLineNumber(LineNumberInfo lineNumberInfo)
Inserts the given line number at the appropriate position in the line number table.
|
static void |
main(java.lang.String[] args)
Small sample application that illustrates the use of this class.
|
void |
reset()
Starts a new code definition.
|
void |
visitAnyAttribute(Clazz clazz,
Attribute attribute)
Visits any Attribute instance.
|
void |
visitAnyInstruction(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
int offset,
Instruction instruction)
Visits any Instruction instance.
|
void |
visitAnyStackMapFrame(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
int offset,
StackMapFrame stackMapFrame)
Visits any StackMapFrame instance.
|
void |
visitAnySwitchInstruction(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
int offset,
SwitchInstruction switchInstruction)
Visits any SwitchInstruction instance.
|
void |
visitAnyTargetInfo(Clazz clazz,
TypeAnnotation typeAnnotation,
TargetInfo targetInfo)
Visits any TargetInfo instance.
|
void |
visitAnyTypeAnnotationsAttribute(Clazz clazz,
TypeAnnotationsAttribute typeAnnotationsAttribute)
Visits any TypeAnnotationsAttribute instance.
|
void |
visitAnyVerificationType(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
int offset,
VerificationType verificationType)
Visits any VerificationType instance.
|
void |
visitBranchInstruction(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
int offset,
BranchInstruction branchInstruction) |
void |
visitCodeAttribute(Clazz clazz,
Method method,
CodeAttribute codeAttribute)
Sets the code that has been built in the given code attribute.
|
void |
visitExceptionInfo(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
ExceptionInfo exceptionInfo) |
void |
visitFullFrame(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
int offset,
FullFrame fullFrame) |
void |
visitLineNumberInfo(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
LineNumberInfo lineNumberInfo) |
void |
visitLineNumberTableAttribute(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
LineNumberTableAttribute lineNumberTableAttribute) |
void |
visitLocalVariableInfo(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
LocalVariableInfo localVariableInfo) |
void |
visitLocalVariableTableAttribute(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
LocalVariableTableAttribute localVariableTableAttribute) |
void |
visitLocalVariableTargetElement(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
TypeAnnotation typeAnnotation,
LocalVariableTargetInfo localVariableTargetInfo,
LocalVariableTargetElement localVariableTargetElement) |
void |
visitLocalVariableTargetInfo(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
TypeAnnotation typeAnnotation,
LocalVariableTargetInfo localVariableTargetInfo) |
void |
visitLocalVariableTypeInfo(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
LocalVariableTypeInfo localVariableTypeInfo) |
void |
visitLocalVariableTypeTableAttribute(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
LocalVariableTypeTableAttribute localVariableTypeTableAttribute) |
void |
visitMoreZeroFrame(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
int offset,
MoreZeroFrame moreZeroFrame) |
void |
visitOffsetTargetInfo(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
TypeAnnotation typeAnnotation,
OffsetTargetInfo offsetTargetInfo) |
void |
visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute) |
void |
visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute) |
void |
visitSameOneFrame(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
int offset,
SameOneFrame sameOneFrame) |
void |
visitStackMapAttribute(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
StackMapAttribute stackMapAttribute) |
void |
visitStackMapTableAttribute(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
StackMapTableAttribute stackMapTableAttribute) |
void |
visitTypeAnnotation(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
TypeAnnotation typeAnnotation) |
void |
visitTypeAnnotation(Clazz clazz,
TypeAnnotation typeAnnotation)
Visits any TypeAnnotation instance.
|
void |
visitTypeArgumentTargetInfo(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
TypeAnnotation typeAnnotation,
TypeArgumentTargetInfo typeArgumentTargetInfo) |
void |
visitUninitializedType(Clazz clazz,
Method method,
CodeAttribute codeAttribute,
int offset,
UninitializedType uninitializedType) |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
visitAnnotationDefaultAttribute, visitAnyAnnotationsAttribute, visitAnyParameterAnnotationsAttribute, visitBootstrapMethodsAttribute, visitConstantValueAttribute, visitDeprecatedAttribute, visitDeprecatedAttribute, visitDeprecatedAttribute, visitDeprecatedAttribute, visitEnclosingMethodAttribute, visitExceptionsAttribute, visitInnerClassesAttribute, visitMethodParametersAttribute, visitModuleAttribute, visitModuleMainClassAttribute, visitModulePackagesAttribute, visitNestHostAttribute, visitNestMembersAttribute, visitPermittedSubclassesAttribute, visitRecordAttribute, visitRuntimeInvisibleAnnotationsAttribute, visitRuntimeInvisibleAnnotationsAttribute, visitRuntimeInvisibleAnnotationsAttribute, visitRuntimeInvisibleAnnotationsAttribute, visitRuntimeInvisibleAnnotationsAttribute, visitRuntimeInvisibleParameterAnnotationsAttribute, visitRuntimeInvisibleTypeAnnotationsAttribute, visitRuntimeInvisibleTypeAnnotationsAttribute, visitRuntimeInvisibleTypeAnnotationsAttribute, visitRuntimeInvisibleTypeAnnotationsAttribute, visitRuntimeInvisibleTypeAnnotationsAttribute, visitRuntimeVisibleAnnotationsAttribute, visitRuntimeVisibleAnnotationsAttribute, visitRuntimeVisibleAnnotationsAttribute, visitRuntimeVisibleAnnotationsAttribute, visitRuntimeVisibleAnnotationsAttribute, visitRuntimeVisibleParameterAnnotationsAttribute, visitRuntimeVisibleTypeAnnotationsAttribute, visitRuntimeVisibleTypeAnnotationsAttribute, visitRuntimeVisibleTypeAnnotationsAttribute, visitRuntimeVisibleTypeAnnotationsAttribute, visitRuntimeVisibleTypeAnnotationsAttribute, visitSignatureAttribute, visitSignatureAttribute, visitSignatureAttribute, visitSignatureAttribute, visitSignatureAttribute, visitSourceDebugExtensionAttribute, visitSourceDirAttribute, visitSourceFileAttribute, visitSyntheticAttribute, visitSyntheticAttribute, visitSyntheticAttribute, visitSyntheticAttribute, visitUnknownAttribute
visitConstantInstruction, visitLookUpSwitchInstruction, visitSimpleInstruction, visitTableSwitchInstruction, visitVariableInstruction
visitLessZeroFrame, visitSameZeroFrame
visitDoubleType, visitFloatType, visitIntegerType, visitLongType, visitNullType, visitObjectType, visitStackDoubleType, visitStackFloatType, visitStackIntegerType, visitStackLongType, visitStackNullType, visitStackObjectType, visitStackTopType, visitStackUninitializedThisType, visitStackUninitializedType, visitTopType, visitUninitializedThisType, visitVariablesDoubleType, visitVariablesFloatType, visitVariablesIntegerType, visitVariablesLongType, visitVariablesNullType, visitVariablesObjectType, visitVariablesTopType, visitVariablesUninitializedThisType, visitVariablesUninitializedType
visitTypeAnnotation, visitTypeAnnotation, visitTypeAnnotation, visitTypeAnnotation
visitCatchTargetInfo, visitEmptyTargetInfo, visitEmptyTargetInfo, visitEmptyTargetInfo, visitFormalParameterTargetInfo, visitSuperTypeTargetInfo, visitThrowsTargetInfo, visitTypeParameterBoundTargetInfo, visitTypeParameterBoundTargetInfo, visitTypeParameterBoundTargetInfo, visitTypeParameterBoundTargetInfo, visitTypeParameterTargetInfo, visitTypeParameterTargetInfo
public CodeAttributeComposer()
public CodeAttributeComposer(boolean allowExternalBranchTargets, boolean allowExternalExceptionOffsets, boolean shrinkInstructions)
allowExternalBranchTargets
- specifies whether branch targets can lie outside the code
fragment of the branch instructions.allowExternalExceptionOffsets
- specifies whether exception offsets can lie outside the
code fragment in which exceptions are defined.shrinkInstructions
- specifies whether instructions should automatically be shrunk before
being written.public CodeAttributeComposer(boolean allowExternalBranchTargets, boolean allowExternalExceptionOffsets, boolean shrinkInstructions, boolean absoluteBranchOffsets)
allowExternalBranchTargets
- specifies whether branch targets can lie outside the code
fragment of the branch instructions.allowExternalExceptionOffsets
- specifies whether exception offsets can lie outside the
code fragment in which exceptions are defined.shrinkInstructions
- specifies whether instructions should automatically be shrunk before
being written.absoluteBranchOffsets
- specifies whether offsets of appended branch instructions and
switch instructions are absolute, that is, relative to the start of the code, instead of
relative to the instructions. This may simplify creating code manually, assuming the
offsets don't overflow.public void reset()
public void beginCodeFragment(int maximumCodeFragmentLength)
maximumCodeFragmentLength
- the maximum length of the code that will be added as part of
this fragment (more precisely, the maximum old instruction offset or label that is
specified, plus one).public int getCodeLength()
public void appendInstruction(int oldInstructionOffset, Instruction instruction)
oldInstructionOffset
- the old offset of the instruction, to which branches and other
references in the current code fragment are pointing.instruction
- the instruction to be appended.public void appendLabel(int oldInstructionOffset)
oldInstructionOffset
- the old offset of the label, to which branches and other references
in the current code fragment are pointing.public void appendInstructions(Instruction[] instructions)
instructions
- the instructions to be appended.public void appendInstruction(Instruction instruction)
instruction
- the instruction to be appended.public void appendException(ExceptionInfo exceptionInfo)
exceptionInfo
- the exception to be appended.public int insertLineNumber(LineNumberInfo lineNumberInfo)
lineNumberInfo
- the line number to be inserted.public int insertLineNumber(int minimumIndex, LineNumberInfo lineNumberInfo)
minimumIndex
- the minimum index where the line number may be inserted.lineNumberInfo
- the line number to be inserted.public void appendLineNumber(LineNumberInfo lineNumberInfo)
lineNumberInfo
- the line number to be appended.public void endCodeFragment()
public void addCodeAttribute(ProgramClass programClass, ProgramMethod programMethod)
public void addCodeAttribute(ProgramClass programClass, ProgramMethod programMethod, ConstantPoolEditor constantPoolEditor)
public void visitAnyAttribute(Clazz clazz, Attribute attribute)
AttributeVisitor
visitAnyAttribute
in interface AttributeVisitor
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
visitCodeAttribute
in interface AttributeVisitor
public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
visitStackMapAttribute
in interface AttributeVisitor
public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
visitStackMapTableAttribute
in interface AttributeVisitor
public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
visitLineNumberTableAttribute
in interface AttributeVisitor
public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
visitLocalVariableTableAttribute
in interface AttributeVisitor
public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
visitLocalVariableTypeTableAttribute
in interface AttributeVisitor
public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute)
AttributeVisitor
visitAnyTypeAnnotationsAttribute
in interface AttributeVisitor
public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
visitRuntimeVisibleTypeAnnotationsAttribute
in interface AttributeVisitor
public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
visitRuntimeInvisibleTypeAnnotationsAttribute
in interface AttributeVisitor
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
InstructionVisitor
visitAnyInstruction
in interface InstructionVisitor
public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
visitBranchInstruction
in interface InstructionVisitor
public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
InstructionVisitor
visitAnySwitchInstruction
in interface InstructionVisitor
public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
visitExceptionInfo
in interface ExceptionInfoVisitor
public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)
StackMapFrameVisitor
visitAnyStackMapFrame
in interface StackMapFrameVisitor
public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
visitSameOneFrame
in interface StackMapFrameVisitor
public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
visitMoreZeroFrame
in interface StackMapFrameVisitor
public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
visitFullFrame
in interface StackMapFrameVisitor
public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType)
VerificationTypeVisitor
visitAnyVerificationType
in interface VerificationTypeVisitor
public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
visitUninitializedType
in interface VerificationTypeVisitor
public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
visitLineNumberInfo
in interface LineNumberInfoVisitor
public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
visitLocalVariableInfo
in interface LocalVariableInfoVisitor
public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
visitLocalVariableTypeInfo
in interface LocalVariableTypeInfoVisitor
public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)
TypeAnnotationVisitor
visitTypeAnnotation
in interface TypeAnnotationVisitor
public void visitTypeAnnotation(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation)
visitTypeAnnotation
in interface TypeAnnotationVisitor
public void visitAnyTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfo targetInfo)
TargetInfoVisitor
visitAnyTargetInfo
in interface TargetInfoVisitor
public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)
visitLocalVariableTargetInfo
in interface TargetInfoVisitor
public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo)
visitOffsetTargetInfo
in interface TargetInfoVisitor
public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo)
visitTypeArgumentTargetInfo
in interface TargetInfoVisitor
public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement)
visitLocalVariableTargetElement
in interface LocalVariableTargetElementVisitor
public static void main(java.lang.String[] args)