⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 methodrewriter.java

📁 配置文件
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
			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 + -