?? methodrewriter.java
字號:
subroutineMap.put(label, subroutine);
}
return subroutine.endIndex + 1;
}
/**
* Return a boolean indicating whether or not this
* try-catch block should be copied to the new class.
*
* @param tryCatch
* @return
*/
private boolean shouldCopy(TryCatchBlockNode tryCatch) {
boolean shouldCopy = true;
int startIndex = getLabelIndex(srcMethod, tryCatch.start);
ArrayList insns = new ArrayList();
for (int i = startIndex; i < srcMethod.instructions.size(); i++) {
AbstractInsnNode insn = getInstruction(srcMethod, i);
if (insn.getType() == AbstractInsnNode.LABEL) {
LabelNode l = (LabelNode) insn;
if (l.label.equals(tryCatch.end)) {
break;
}
} else {
insns.add(insn);
}
}
if (insns.size() == 1) {
AbstractInsnNode insn = (AbstractInsnNode) insns.get(0);
shouldCopy = (insn.getOpcode() != Opcodes.JSR);
}
return shouldCopy;
}
/**
* Return a boolean indicating whether the variable visibility should
* be reduced.
*
* @param method
* @return
*/
private boolean shouldReduceVariableVisibility(MethodNode method) {
boolean shouldReduce = false;
if (getLastInstruction(method) instanceof LabelNode) {
List instructions = updatedMethod.instructions;
int instructionCount = instructions.size();
AbstractInsnNode node = getInstruction(method, instructionCount - 2);
if (node instanceof InsnNode) {
InsnNode insnNode = (InsnNode) node;
switch (insnNode.getOpcode()) {
case Opcodes.IRETURN:
case Opcodes.LRETURN:
case Opcodes.FRETURN:
case Opcodes.DRETURN:
case Opcodes.ARETURN:
case Opcodes.RETURN:
case Opcodes.ATHROW:
shouldReduce = true;
break;
}
}
}
return shouldReduce;
}
/**
* Sort the try/catch blocks such that they are associated with
* the smallest region that surrounds that block.
*
* @param methodRegion
*/
private void sortTryCatchBlocks(Region methodRegion) {
Iterator blocks = srcMethod.tryCatchBlocks.iterator();
while (blocks.hasNext()) {
Region enclosingRegion = methodRegion;
TryCatchBlockNode block = (TryCatchBlockNode) blocks.next();
Iterator regions = subroutineMap.values().iterator();
while (regions.hasNext()) {
Region region = (Region) regions.next();
if (region.encloses(block)) {
if (enclosingRegion == null) {
enclosingRegion = region;
} else {
// Pick the smallest region that encloses the block
if (region.getLength() < enclosingRegion.getLength()) {
enclosingRegion = region;
}
}
}
}
enclosingRegion.addTryCatchBlock(block);
}
}
/**
* Return the target labels used in generation of the stack map attribute.
*
* @return
*/
private Set findTargetLabels() {
Set targetLabels = new HashSet();
Iterator insns = updatedMethod.instructions.iterator();
while (insns.hasNext()) {
AbstractInsnNode insnNode = (AbstractInsnNode) insns.next();
switch (insnNode.getType()) {
case AbstractInsnNode.JUMP_INSN:
JumpInsnNode jumpInsnNode = (JumpInsnNode) insnNode;
targetLabels.add(jumpInsnNode.label);
break;
case AbstractInsnNode.LOOKUPSWITCH_INSN:
{
LookupSwitchInsnNode lookupSwitchNode = (LookupSwitchInsnNode) insnNode;
Iterator labels = lookupSwitchNode.labels.iterator();
while (labels.hasNext()) {
Label label = (Label) labels.next();
targetLabels.add(label);
}
targetLabels.add(lookupSwitchNode.dflt);
}
break;
case AbstractInsnNode.TABLESWITCH_INSN:
{
TableSwitchInsnNode tableSwitchNode = (TableSwitchInsnNode) insnNode;
Iterator labels = tableSwitchNode.labels.iterator();
while (labels.hasNext()) {
Label label = (Label) labels.next();
targetLabels.add(label);
}
targetLabels.add(tableSwitchNode.dflt);
}
break;
}
}
Iterator blocks = updatedMethod.tryCatchBlocks.iterator();
while (blocks.hasNext()) {
TryCatchBlockNode tryCatchBlock = (TryCatchBlockNode) blocks.next();
targetLabels.add(tryCatchBlock.handler);
}
return targetLabels;
}
/**
* Return the instruction at the specified index.
*
* @param method
* @param index
* @return
*/
private AbstractInsnNode getInstruction(MethodNode method, int index) {
List instructions = method.instructions;
return (AbstractInsnNode) ((index < instructions.size()) ? instructions.get(index) : null);
}
/**
* Return the index of the specified label within the specified method node.
*
* @param methodNode
* @param label
* @return
*/
private int getLabelIndex(PreverifierMethodNode methodNode, Label label) {
Integer i = (Integer) methodNode.getLabelIndices().get(label);
return i.intValue();
}
/**
* Return the last instruction in the specified method.
*
* @param method
* @return
*/
private AbstractInsnNode getLastInstruction(MethodNode method) {
return getInstruction(method, method.instructions.size() - 1);
}
/**
* Map the specified list of labels into an array of labels
* mapped into the target region.
*
* @param region
* @param labels
* @return
*/
private Label[] getMappedLabelArray(Region region, List labels) {
Label[] mappedLabels = new Label[labels.size()];
for (int i = 0; i < mappedLabels.length; i++) {
mappedLabels[i] = region.getMappedLabel((Label) labels.get(i));
}
return mappedLabels;
}
/**
* Return a method indicating whether the specified label is the start
* of a referenced subroutine.
*
* @param label
* @return
*/
private boolean isSubroutineStart(Label label) {
return subroutineMap.containsKey(label);
}
/**
* Visit the specified instruction and do the right thing.
*
* @param method
* @param region
* @param insnNode
* @throws AnalyzerException
*/
private void visitInstruction(
MethodNode method,
Region region,
AbstractInsnNode insnNode)
throws AnalyzerException
{
int opcode = insnNode.getOpcode();
switch (opcode) {
case Opcodes.JSR:
visitJumpToSubroutine(method, region, (JumpInsnNode) insnNode);
break;
case Opcodes.IFEQ:
case Opcodes.IFNE:
case Opcodes.IFLT:
case Opcodes.IFGE:
case Opcodes.IFGT:
case Opcodes.IFLE:
case Opcodes.IF_ICMPEQ:
case Opcodes.IF_ICMPNE:
case Opcodes.IF_ICMPLT:
case Opcodes.IF_ICMPGE:
case Opcodes.IF_ICMPGT:
case Opcodes.IF_ICMPLE:
case Opcodes.IF_ACMPEQ:
case Opcodes.IF_ACMPNE:
case Opcodes.GOTO:
case Opcodes.IFNULL:
case Opcodes.IFNONNULL:
visitJump(method, region, (JumpInsnNode) insnNode);
break;
case Opcodes.LOOKUPSWITCH:
visitLookupSwitch(method, region, (LookupSwitchInsnNode) insnNode);
break;
case Opcodes.TABLESWITCH:
visitTableSwitch(method, region, (TableSwitchInsnNode) insnNode);
break;
default:
insnNode.accept(method);
}
}
/**
* Visit the specified jump instructions, mapping the labels into the target
* method.
*
* @param method
* @param region
* @param jumpNode
*/
private void visitJump(MethodNode method, Region region, JumpInsnNode jumpNode) {
Label mappedLabel = region.getMappedLabel(jumpNode.label);
JumpInsnNode newJumpNode = new JumpInsnNode(jumpNode.getOpcode(), mappedLabel);
newJumpNode.accept(method);
}
/**
* Visit a JSR instruction... Inlining the subroutine.
*
* @param method
* @param region
* @param jumpNode
* @throws AnalyzerException
*/
private void visitJumpToSubroutine(MethodNode method, Region region, JumpInsnNode jumpNode)
throws AnalyzerException
{
// Back up and see if we need to remap a local variable label
// The WTK preverifier extends the scope of a local variable
// one instruction further if the last instruction of the block
// is a variable store instruction
AbstractInsnNode insnNode = getLastInstruction(updatedMethod);
if (insnNode instanceof VarInsnNode) {
List instructions = updatedMethod.instructions;
AbstractInsnNode insnNode2 =
(AbstractInsnNode) instructions.get(instructions.size() - 2);
if (insnNode2 instanceof LabelNode) {
// Looks like we have the correct situation here.
// Introduce a new label as the last instruction
// and add it to the label map to be used when
// adding the local variables
LabelNode labelNode = (LabelNode) insnNode2;
ArrayList localVariables =
(ArrayList) localVariableByEndLabelMap.get(labelNode.label);
if (localVariables != null)
{
Iterator vars = localVariables.iterator();
while (vars.hasNext()) {
LocalVariableNode var = (LocalVariableNode) vars.next();
var.end = new Label();
method.visitLabel(var.end);
}
}
}
}
// Inline the subroutine
Subroutine subroutine = (Subroutine) subroutineMap.get(jumpNode.label);
subroutine.setParentRegion(region);
copyRegion(method, subroutine);
}
/**
* Visit the specified label in the context of the region. Handle
* all things related to that label.
*
* @param method
* @param region
* @param label
*/
private void visitLabel(MethodNode method, Region region, Label label) {
Label mappedLabel = region.getMappedLabel(label);
method.visitLabel(mappedLabel);
// Check for any related attributes
LineNumberNode lineNumber = (LineNumberNode) lineNumberMap.get(label);
if (lineNumber != null) {
method.visitLineNumber(lineNumber.line, mappedLabel);
}
ArrayList localVariables = (ArrayList) localVariableByStartLabelMap.get(label);
if (localVariables != null) {
Iterator vars = localVariables.iterator();
while (vars.hasNext()) {
int localVariableCount = method.localVariables.size();
LocalVariableNode localVariable = (LocalVariableNode) vars.next();
method.visitLocalVariable(
localVariable.name,
localVariable.desc,
localVariable.signature,
region.getMappedLabel(localVariable.start),
region.getMappedLabel(localVariable.end),
localVariable.index);
LocalVariableNode newLocalVariable =
(LocalVariableNode) method.localVariables.get(localVariableCount);
addNewLocalVariableByEnd(newLocalVariable);
}
}
}
/**
* Visit the specified instruction, mapping the labels into the target
* method.
*
* @param codeVisitor
* @param region
* @param node
*/
private void visitLookupSwitch(MethodNode codeVisitor, Region region, LookupSwitchInsnNode node) {
Label dflt = region.getMappedLabel(node.dflt);
int[] keys = new int[node.keys.size()];
for (int i = 0; i < keys.length; i++) {
keys[i] = ((Integer) node.keys.get(i)).intValue();
}
Label[] labels = getMappedLabelArray(region, node.labels);
LookupSwitchInsnNode newSwitch = new LookupSwitchInsnNode(dflt, keys, labels);
newSwitch.accept(codeVisitor);
}
/**
* Visit the specified instructions, mapping the labels into the target
* method.
*
* @param codeVisitor
* @param region
* @param node
*/
private void visitTableSwitch(MethodNode codeVisitor, Region region, TableSwitchInsnNode node) {
Label dflt = region.getMappedLabel(node.dflt);
Label[] labels = getMappedLabelArray(region, node.labels);
TableSwitchInsnNode newSwitch =
new TableSwitchInsnNode(node.min, node.max, dflt, labels);
newSwitch.accept(codeVisitor);
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -