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

📄 methodgen.java

📁 Java Bytecode Editor 是一个 JAVA 的字节码反汇编和修改器。它可以很方便的修改已经编译成 Class 文件的 JAVA 文件。
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
			addAttribute(code);
		}

		ExceptionTable et = null;

		if (throws_vec.size() > 0)
			addAttribute(et = getExceptionTable(cp)); // Add `Exceptions' if
														// there are
		// "throws" clauses

		Method m = new Method(access_flags, name_index, signature_index,
				getAttributes(), cp.getConstantPool());

		// Undo effects of adding attributes
		if (lvt != null)
			removeCodeAttribute(lvt);
		if (lnt != null)
			removeCodeAttribute(lnt);
		if (code != null)
			removeAttribute(code);
		if (et != null)
			removeAttribute(et);

		return m;
	}

	/**
	 * Remove all NOPs from the instruction list (if possible) and update every
	 * object refering to them, i.e., branch instructions, local variables and
	 * exception handlers.
	 */
	public void removeNOPs() {
		if (il != null) {
			InstructionHandle next;
			/*
			 * Check branch instructions.
			 */
			for (InstructionHandle ih = il.getStart(); ih != null; ih = next) {
				next = ih.next;

				if ((next != null) && (ih.getInstruction() instanceof NOP)) {
					try {
						il.delete(ih);
					} catch (TargetLostException e) {
						InstructionHandle[] targets = e.getTargets();

						for (int i = 0; i < targets.length; i++) {
							InstructionTargeter[] targeters = targets[i]
									.getTargeters();

							for (int j = 0; j < targeters.length; j++)
								targeters[j].updateTarget(targets[i], next);
						}
					}
				}
			}
		}
	}

	/**
	 * Set maximum number of local variables.
	 */
	public void setMaxLocals(int m) {
		max_locals = m;
	}

	public int getMaxLocals() {
		return max_locals;
	}

	/**
	 * Set maximum stack size for this method.
	 */
	public void setMaxStack(int m) {
		max_stack = m;
	}

	public int getMaxStack() {
		return max_stack;
	}

	/**
	 * @return class that contains this method
	 */
	public String getClassName() {
		return class_name;
	}

	public void setClassName(String class_name) {
		this.class_name = class_name;
	}

	public void setReturnType(Type return_type) {
		setType(return_type);
	}

	public Type getReturnType() {
		return getType();
	}

	public void setArgumentTypes(Type[] arg_types) {
		this.arg_types = arg_types;
	}

	public Type[] getArgumentTypes() {
		return (Type[]) arg_types.clone();
	}

	public void setArgumentType(int i, Type type) {
		arg_types[i] = type;
	}

	public Type getArgumentType(int i) {
		return arg_types[i];
	}

	public void setArgumentNames(String[] arg_names) {
		this.arg_names = arg_names;
	}

	public String[] getArgumentNames() {
		return (String[]) arg_names.clone();
	}

	public void setArgumentName(int i, String name) {
		arg_names[i] = name;
	}

	public String getArgumentName(int i) {
		return arg_names[i];
	}

	public InstructionList getInstructionList() {
		return il;
	}

	public void setInstructionList(InstructionList il) {
		this.il = il;
	}

	public String getSignature() {
		return Type.getMethodSignature(type, arg_types);
	}

	/**
	 * Computes max. stack size by performing control flow analysis.
	 */
	public void setMaxStack() {
		if (il != null)
			max_stack = getMaxStack(cp, il, getExceptionHandlers());
		else
			max_stack = 0;
	}

	/**
	 * Compute maximum number of local variables.
	 */
	public void setMaxLocals() {
		if (il != null) {
			int max = isStatic() ? 0 : 1;

			if (arg_types != null)
				for (int i = 0; i < arg_types.length; i++)
					max += arg_types[i].getSize();

			for (InstructionHandle ih = il.getStart(); ih != null; ih = ih
					.getNext()) {
				Instruction ins = ih.getInstruction();

				if ((ins instanceof LocalVariableInstruction)
						|| (ins instanceof RET) || (ins instanceof IINC)) {
					int index = ((IndexedInstruction) ins).getIndex()
							+ ((TypedInstruction) ins).getType(cp).getSize();

					if (index > max)
						max = index;
				}
			}

			max_locals = max;
		} else
			max_locals = 0;
	}

	/**
	 * Do not/Do produce attributes code attributesLineNumberTable and
	 * LocalVariableTable, like javac -O
	 */
	public void stripAttributes(boolean flag) {
		strip_attributes = flag;
	}

	static final class BranchTarget {
		InstructionHandle target;

		int stackDepth;

		BranchTarget(InstructionHandle target, int stackDepth) {
			this.target = target;
			this.stackDepth = stackDepth;
		}
	}

	static final class BranchStack {
		Stack<BranchTarget> branchTargets = new Stack<BranchTarget>();

		Hashtable<InstructionHandle, BranchTarget> visitedTargets = new Hashtable<InstructionHandle, BranchTarget>();

		public void push(InstructionHandle target, int stackDepth) {
			if (visited(target))
				return;

			branchTargets.push(visit(target, stackDepth));
		}

		public BranchTarget pop() {
			if (!branchTargets.empty()) {
				BranchTarget bt = (BranchTarget) branchTargets.pop();
				return bt;
			}

			return null;
		}

		private final BranchTarget visit(InstructionHandle target,
				int stackDepth) {
			BranchTarget bt = new BranchTarget(target, stackDepth);
			visitedTargets.put(target, bt);

			return bt;
		}

		private final boolean visited(InstructionHandle target) {
			return (visitedTargets.get(target) != null);
		}
	}

	/**
	 * Computes stack usage of an instruction list by performing control flow
	 * analysis.
	 * 
	 * @return maximum stack depth used by method
	 */
	public static int getMaxStack(ConstantPoolGen cp, InstructionList il,
			CodeExceptionGen[] et) {
		BranchStack branchTargets = new BranchStack();

		/*
		 * Initially, populate the branch stack with the exception handlers,
		 * because these aren't (necessarily) branched to explicitly. in each
		 * case, the stack will have depth 1, containing the exception object.
		 */
		for (int i = 0; i < et.length; i++) {
			InstructionHandle handler_pc = et[i].getHandlerPC();
			if (handler_pc != null)
				branchTargets.push(handler_pc, 1);
		}

		int stackDepth = 0, maxStackDepth = 0;
		InstructionHandle ih = il.getStart();

		while (ih != null) {
			Instruction instruction = ih.getInstruction();
			short opcode = instruction.getOpcode();
			int delta = instruction.produceStack(cp)
					- instruction.consumeStack(cp);

			stackDepth += delta;
			if (stackDepth > maxStackDepth)
				maxStackDepth = stackDepth;

			// choose the next instruction based on whether current is a branch.
			if (instruction instanceof BranchInstruction) {
				BranchInstruction branch = (BranchInstruction) instruction;
				if (instruction instanceof Select) {
					// explore all of the select's targets. the default target
					// is handled
					// below.
					Select select = (Select) branch;
					InstructionHandle[] targets = select.getTargets();
					for (int i = 0; i < targets.length; i++)
						branchTargets.push(targets[i], stackDepth);
					// nothing to fall through to.
					ih = null;
				} else if (!(branch instanceof IfInstruction)) {
					// if an instruction that comes back to following PC,
					// push next instruction, with stack depth reduced by 1.
					if (opcode == Constants.JSR || opcode == Constants.JSR_W)
						branchTargets.push(ih.getNext(), stackDepth - 1);
					ih = null;
				}
				// for all branches, the target of the branch is pushed on the
				// branch stack.
				// conditional branches have a fall through case, selects don't,
				// and
				// jsr/jsr_w return to the next instruction.
				branchTargets.push(branch.getTarget(), stackDepth);
			} else {
				// check for instructions that terminate the method.
				if (opcode == Constants.ATHROW
						|| opcode == Constants.RET
						|| (opcode >= Constants.IRETURN && opcode <= Constants.RETURN))
					ih = null;
			}
			// normal case, go to the next instruction.
			if (ih != null)
				ih = ih.getNext();
			// if we have no more instructions, see if there are any deferred
			// branches to explore.
			if (ih == null) {
				BranchTarget bt = branchTargets.pop();
				if (bt != null) {
					ih = bt.target;
					stackDepth = bt.stackDepth;
				}
			}
		}

		return maxStackDepth;
	}

	private ArrayList<MethodObserver> observers;

	/**
	 * Add observer for this object.
	 */
	public void addObserver(MethodObserver o) {
		if (observers == null)
			observers = new ArrayList<MethodObserver>();

		observers.add(o);
	}

	/**
	 * Remove observer for this object.
	 */
	public void removeObserver(MethodObserver o) {
		if (observers != null)
			observers.remove(o);
	}

	/**
	 * Call notify() method on all observers. This method is not called
	 * automatically whenever the state has changed, but has to be called by the
	 * user after he has finished editing the object.
	 */
	public void update() {
		if (observers != null)
			for (Iterator e = observers.iterator(); e.hasNext();)
				((MethodObserver) e.next()).notify(this);
	}

	/**
	 * Return string representation close to declaration format, `public static
	 * void main(String[]) throws IOException', e.g.
	 * 
	 * @return String representation of the method.
	 */
	public final String toString() {
		String access = Utility.accessToString(access_flags);
		String signature = Type.getMethodSignature(type, arg_types);

		signature = Utility.methodSignatureToString(signature, name, access,
				true, getLocalVariableTable(cp));

		StringBuffer buf = new StringBuffer(signature);

		if (throws_vec.size() > 0) {
			for (Iterator e = throws_vec.iterator(); e.hasNext();)
				buf.append("\n\t\tthrows " + e.next());
		}

		return buf.toString();
	}

	/**
	 * @return deep copy of this method
	 */
	public MethodGen copy(String class_name, ConstantPoolGen cp) {
		Method m = ((MethodGen) clone()).getMethod();
		MethodGen mg = new MethodGen(m, class_name, this.cp);

		if (this.cp != cp) {
			mg.setConstantPool(cp);
			mg.getInstructionList().replaceConstantPool(this.cp, cp);
		}

		return mg;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -