public abstract class InstructionListUtils extends StackMapUtils
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 one wishes 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)
set_current_stack_map_table(mg, cg.getMajor());
fix_local_variable_table(mg);
// Create a map of Uninitialized_variable_info offsets to
// InstructionHandles.
build_unitialized_NEW_map(il);
This is where you would insert your code to modify the current method (mg).
Most often this is done with members of the org.apache.bcel.generic
package. 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.
update_uninitialized_NEW_offsets(il);
create_new_stack_map_attribute(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);
}
}
}
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.debug_instrument, first_local_index, initial_locals_count, initial_type_list, live_range_end, live_range_operand_size, live_range_start, live_range_type, needStackMap, number_active_locals, pool, running_offset, smta, stack_map_table, stack_types| Constructor and Description |
|---|
InstructionListUtils() |
| Modifier and Type | Method and Description |
|---|---|
protected 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 org.apache.bcel.generic.InstructionList |
build_il(org.apache.bcel.generic.Instruction... instructions)
Convenience function to build an instruction list.
|
protected org.apache.bcel.classfile.StackMapType[] |
calculate_live_local_types(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 org.apache.bcel.classfile.StackMapType[] |
calculate_live_stack_types(org.apache.bcel.verifier.structurals.OperandStack stack)
Compute the StackMapTypes of the items on the execution stack as described by the OperandStack
argument.
|
protected void |
delete_instructions(org.apache.bcel.generic.MethodGen mg,
org.apache.bcel.generic.InstructionHandle start_ih,
org.apache.bcel.generic.InstructionHandle end_ih)
Delete instruction(s) from start_ih thru end_ih in an instruction list.
|
protected void |
insert_at_method_start(org.apache.bcel.generic.MethodGen mg,
org.apache.bcel.generic.InstructionList new_il)
Inserts an instruction list at the beginning of a method.
|
protected void |
insert_before_handle(org.apache.bcel.generic.MethodGen mg,
org.apache.bcel.generic.InstructionHandle ih,
@Nullable org.apache.bcel.generic.InstructionList new_il,
boolean redirect_branches)
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).
|
private void |
print_il(org.apache.bcel.generic.InstructionHandle start,
String label)
Print a BCEL instruction list to the debug_instrument log.
|
protected void |
replace_instructions(org.apache.bcel.generic.MethodGen mg,
org.apache.bcel.generic.InstructionList il,
org.apache.bcel.generic.InstructionHandle ih,
@Nullable org.apache.bcel.generic.InstructionList new_il)
Replace instruction ih in list il with the instructions in new_il.
|
add_new_argument, add_new_parameter, add_string, adjust_code_for_locals_change, bcel_calc_stack_types, build_unitialized_NEW_map, create_local_from_live_range, create_method_scope_local, create_new_stack_map_attribute, fetch_current_stack_map_table, find_stack_map_equal, find_stack_map_index_after, find_stack_map_index_before, fix_local_variable_table, gen_locals_from_byte_codes, gen_locals_from_byte_codes, gen_locals, generate_StackMapType_from_Type, generate_Type_from_StackMapType, get_attribute_name, get_local_variable_type_table_attribute, get_stack_map_table_attribute, getSize, is_local_variable_type_table, is_stack_map_table, modify_stack_maps_for_switches, print_stack_map_table, remove_local_variable_type_table, set_current_stack_map_table, set_method_stack_types, typeToClassGetName, update_full_frame_stack_map_entries, update_stack_map_offset, update_uninitialized_NEW_offsetsprotected final void append_inst(org.apache.bcel.generic.InstructionList il,
org.apache.bcel.generic.Instruction inst)
il - InstructionList to be modifiedinst - Instruction to be appendedprotected final void insert_at_method_start(org.apache.bcel.generic.MethodGen mg,
org.apache.bcel.generic.InstructionList new_il)
mg - MethodGen of method to be modifiednew_il - InstructionList holding the new codeprotected final void insert_before_handle(org.apache.bcel.generic.MethodGen mg,
org.apache.bcel.generic.InstructionHandle ih,
@Nullable org.apache.bcel.generic.InstructionList new_il,
boolean redirect_branches)
mg - MethodGen containing the instruction handleih - InstructionHandle indicating where to insert new codenew_il - InstructionList holding the new coderedirect_branches - flag indicating if branch targets should be moved from ih to new_ilprivate void print_il(org.apache.bcel.generic.InstructionHandle start,
String label)
start - start of the instruction listlabel - a descriptive string for the instruction listprotected final org.apache.bcel.generic.InstructionList build_il(org.apache.bcel.generic.Instruction... instructions)
instructions - a variable number of BCEL instructionsprotected final void delete_instructions(org.apache.bcel.generic.MethodGen mg,
org.apache.bcel.generic.InstructionHandle start_ih,
org.apache.bcel.generic.InstructionHandle end_ih)
mg - MethodGen containing the instruction handlesstart_ih - InstructionHandle indicating first instruction to be deletedend_ih - InstructionHandle indicating last instruction to be deletedprotected final org.apache.bcel.classfile.StackMapType[] calculate_live_local_types(org.apache.bcel.generic.MethodGen mg,
int location)
mg - MethodGen for the current methodlocation - the code location to be evaluatedprotected final org.apache.bcel.classfile.StackMapType[] calculate_live_stack_types(org.apache.bcel.verifier.structurals.OperandStack stack)
stack - an OperandStack objectprotected final void replace_instructions(org.apache.bcel.generic.MethodGen mg,
org.apache.bcel.generic.InstructionList il,
org.apache.bcel.generic.InstructionHandle ih,
@Nullable org.apache.bcel.generic.InstructionList new_il)
mg - MethodGen containing the instruction handleil - InstructionList containing ihih - InstructionHandle indicating where to insert new codenew_il - InstructionList holding the new code