Package org.plumelib.bcelutil
Class InstructionListUtils
java.lang.Object
org.plumelib.bcelutil.StackMapUtils
org.plumelib.bcelutil.InstructionListUtils
This class provides utility methods to maintain and modify a method's InstructionList within a
Java class file. It is a subclass of
StackMapUtils
and thus handles
all the StackMap side effects of InstructionList modification. It can be thought of as an
extension to BCEL.
BCEL ought to automatically build and maintain the StackMapTable in a manner similar to the LineNumberTable and the LocalVariableTable. However, for historical reasons, it does not.
If you wish to modify a Java class file, you should create a subclass of InstructionListUtils to do the modifications. Then a rough program template for that class would be:
import org.apache.bcel.classfile.*; import org.apache.bcel.generic.*; try { // Parse the bytes of the classfile, die on any errors ClassParser parser = new ClassParser(new ByteArrayInputStream(classfileBuffer), className); JavaClass jc = parser.parse(); // Transform the file modifyClass(jc); } catch (Throwable e) { throw new RuntimeException("Unexpected error", e); } void modifyClass(JavaClass jc) { ClassGen cg = new ClassGen(jc); String classname = cg.getClassName(); //save ConstantPool for use by StackMapUtils pool = cg.getConstantPool(); for (Method m : cg.getMethods()) { try { MethodGen mg = new MethodGen(m, classname, pool); // Get the instruction list and skip methods with no instructions InstructionList il = mg.getInstructionList(); if (il == null) { continue; } // Get existing StackMapTable (if present) setCurrentStackMapTable(mg, cg.getMajor()); fixLocalVariableTable(mg); // Create a map of Uninitialized_variable_info offsets to // InstructionHandles. buildUninitializedNewMap(il); This is where you would insert your code to modify the current method (mg). Most often this is done with members of thepackage. However, you should use the members of InstrutionListUtils to update the byte code instructions of mg rather than similar methods in the BCEL generic package in order to maintain the integrity of the method's StackMapTable. // Update the Uninitialized_variable_info offsets before // we write out the new StackMapTable. updateUninitializedNewOffsets(il); createNewStackMapAttribute(mg); // Update the instruction list mg.setInstructionList(il); mg.update(); // Update the max stack mg.setMaxStack(); mg.setMaxLocals(); mg.update(); remove_local_variable_type_table(mg); // Update the method in the class cg.replaceMethod(m, mg.getMethod()); } catch (Throwable t) { throw new Error("Unexpected error processing " + classname + "." + m.getName(), t); } } }invalid @link
org.apache.bcel.generic
It one only wishes to examine a class file, the use of this class is not necessary. See BcelUtil
for notes on inspecting a Java class file.
-
Field Summary
Fields inherited from class org.plumelib.bcelutil.StackMapUtils
debugInstrument, firstLocalIndex, initialLocalsCount, initialTypeList, liveRangeEnd, liveRangeOperandSize, liveRangeStart, liveRangeType, needStackMap, numberActiveLocals, pool, runningOffset, smta, stackMapTable, stackTypes
-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionprotected final void
append_inst
(org.apache.bcel.generic.InstructionList il, org.apache.bcel.generic.Instruction inst) Appends the specified instruction to the end of the specified list.protected final org.apache.bcel.generic.InstructionList
build_il
(org.apache.bcel.generic.Instruction... instructions) Convenience function to build an instruction list.protected final org.apache.bcel.classfile.StackMapType[]
calculateLiveLocalTypes
(org.apache.bcel.generic.MethodGen mg, int location) Compute the StackMapTypes of the live variables of the current method at a specific location within the method.protected final org.apache.bcel.classfile.StackMapType[]
calculateLiveStackTypes
(org.apache.bcel.verifier.structurals.OperandStack stack) Compute the StackMapTypes of the items on the execution stack as described by the OperandStack argument.protected final void
delete_instructions
(org.apache.bcel.generic.MethodGen mg, org.apache.bcel.generic.InstructionHandle startIh, org.apache.bcel.generic.InstructionHandle endIh) Delete instruction(s) from startIh thru endIh in an instruction list.protected final void
insertAtMethodStart
(org.apache.bcel.generic.MethodGen mg, org.apache.bcel.generic.InstructionList newIl) Inserts an instruction list at the beginning of a method.protected final void
insertBeforeHandle
(org.apache.bcel.generic.MethodGen mg, org.apache.bcel.generic.InstructionHandle ih, @Nullable org.apache.bcel.generic.InstructionList newIl, boolean redirectBranches) Inserts a new instruction list into an existing instruction list just prior to the indicated instruction handle (which must be a member of the existing instruction list).protected final void
replaceInstructions
(org.apache.bcel.generic.MethodGen mg, org.apache.bcel.generic.InstructionList il, org.apache.bcel.generic.InstructionHandle ih, @Nullable org.apache.bcel.generic.InstructionList newIl) Replace instruction ih in list il with the instructions in newIl.Methods inherited from class org.plumelib.bcelutil.StackMapUtils
addNewParameter, addString, adjust_code_for_locals_change, bcelCalcStackTypes, buildUninitializedNewMap, create_local_from_live_range, create_method_scope_local, createNewStackMapAttribute, findStackMapEqual, findStackMapIndexAfter, findStackMapIndexBefore, fixLocalVariableTable, gen_locals, gen_locals_from_byte_codes, gen_locals_from_byte_codes, generate_Type_from_StackMapType, generateStackMapTypeFromType, get_attribute_name, get_local_variable_type_table_attribute, getSize, getStackMapTable_attribute, is_local_variable_type_table, isStackMapTable, modifyStackMapsForSwitches, printStackMapTable, remove_local_variable_type_table, set_method_stackTypes, setCurrentStackMapTable, typeToClassGetName, update_full_frameStackMap_entries, updateStackMapOffset, updateUninitializedNewOffsets
-
Constructor Details
-
InstructionListUtils
public InstructionListUtils()Create a new InstructionListUtils.
-
-
Method Details
-
append_inst
protected final void append_inst(org.apache.bcel.generic.InstructionList il, org.apache.bcel.generic.Instruction inst) Appends the specified instruction to the end of the specified list. Required because for some reason you can't directly append jump instructions to the list -- but you can create new ones and append them.- Parameters:
il
- InstructionList to be modifiedinst
- Instruction to be appended
-
insertAtMethodStart
protected final void insertAtMethodStart(org.apache.bcel.generic.MethodGen mg, org.apache.bcel.generic.InstructionList newIl) Inserts an instruction list at the beginning of a method.- Parameters:
mg
- MethodGen of method to be modifiednewIl
- InstructionList holding the new code
-
insertBeforeHandle
protected final void insertBeforeHandle(org.apache.bcel.generic.MethodGen mg, org.apache.bcel.generic.InstructionHandle ih, @Nullable org.apache.bcel.generic.InstructionList newIl, boolean redirectBranches) Inserts a new instruction list into an existing instruction list just prior to the indicated instruction handle (which must be a member of the existing instruction list). If newIl is null, do nothing.- Parameters:
mg
- MethodGen containing the instruction handleih
- InstructionHandle indicating where to insert new codenewIl
- InstructionList holding the new coderedirectBranches
- flag indicating if branch targets should be moved from ih to newIl
-
build_il
protected final org.apache.bcel.generic.InstructionList build_il(org.apache.bcel.generic.Instruction... instructions) Convenience function to build an instruction list.- Parameters:
instructions
- a variable number of BCEL instructions- Returns:
- an InstructionList
-
delete_instructions
protected final void delete_instructions(org.apache.bcel.generic.MethodGen mg, org.apache.bcel.generic.InstructionHandle startIh, org.apache.bcel.generic.InstructionHandle endIh) Delete instruction(s) from startIh thru endIh in an instruction list. startIh may be the first instruction of the list, but endIh must not be the last instruction of the list. startIh may be equal to endIh. There must not be any targeters on any of the instructions to be deleted except for startIh. Those targeters will be moved to the first instruction following endIh.- Parameters:
mg
- MethodGen containing the instruction handlesstartIh
- InstructionHandle indicating first instruction to be deletedendIh
- InstructionHandle indicating last instruction to be deleted
-
calculateLiveLocalTypes
protected final org.apache.bcel.classfile.StackMapType[] calculateLiveLocalTypes(org.apache.bcel.generic.MethodGen mg, int location) Compute the StackMapTypes of the live variables of the current method at a specific location within the method. There may be gaps ("Bogus" or non-live slots) so we can't just count the number of live variables, we must find the max index of all the live variables.- Parameters:
mg
- MethodGen for the current methodlocation
- the code location to be evaluated- Returns:
- an array of StackMapType describing the live locals at location
-
calculateLiveStackTypes
protected final org.apache.bcel.classfile.StackMapType[] calculateLiveStackTypes(org.apache.bcel.verifier.structurals.OperandStack stack) Compute the StackMapTypes of the items on the execution stack as described by the OperandStack argument.- Parameters:
stack
- an OperandStack object- Returns:
- an array of StackMapType describing the stack contents
-
replaceInstructions
protected final void replaceInstructions(org.apache.bcel.generic.MethodGen mg, org.apache.bcel.generic.InstructionList il, org.apache.bcel.generic.InstructionHandle ih, @Nullable org.apache.bcel.generic.InstructionList newIl) Replace instruction ih in list il with the instructions in newIl. If newIl is null, do nothing.- Parameters:
mg
- MethodGen containing the instruction handleil
- InstructionList containing ihih
- InstructionHandle indicating where to insert new codenewIl
- InstructionList holding the new code
-