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

📄 methodgen.java

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

/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" and
 *    "Apache BCEL" must not be used to endorse or promote products
 *    derived from this software without prior written permission. For
 *    written permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    "Apache BCEL", nor may "Apache" appear in their name, without
 *    prior written permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

import org.apache.bcel.Constants;
import org.apache.bcel.classfile.*;
import java.util.*;

/**
 * Template class for building up a method. This is done by defining exception
 * handlers, adding thrown exceptions, local variables and attributes, whereas
 * the `LocalVariableTable' and `LineNumberTable' attributes will be set
 * automatically for the code. Use stripAttributes() if you don't like this.
 * 
 * While generating code it may be necessary to insert NOP operations. You can
 * use the `removeNOPs' method to get rid off them. The resulting method object
 * can be obtained via the `getMethod()' method.
 * 
 * @version $Id: MethodGen.java,v 1.4 2006/08/23 13:48:30 andos Exp $
 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
 * @author <A HREF="http://www.vmeng.com/beard">Patrick C. Beard</A>
 *         [setMaxStack()]
 * @see InstructionList
 * @see Method
 */
public class MethodGen extends FieldGenOrMethodGen {
	/**
	 * 
	 */
	private static final long serialVersionUID = -2671312770633709457L;

	private String class_name;

	private Type[] arg_types;

	private String[] arg_names;

	private int max_locals;

	private int max_stack;

	private InstructionList il;

	private boolean strip_attributes;


	private ArrayList<LocalVariableGen> variable_vec = new ArrayList<LocalVariableGen>();

	private ArrayList<LineNumberGen> line_number_vec = new ArrayList<LineNumberGen>();

	private ArrayList<CodeExceptionGen> exception_vec = new ArrayList<CodeExceptionGen>();

	private ArrayList<String> throws_vec = new ArrayList<String>();

	private ArrayList<Attribute> code_attrs_vec = new ArrayList<Attribute>();

	/**
	 * Declare method. If the method is non-static the constructor automatically
	 * declares a local variable `$this' in slot 0. The actual code is contained
	 * in the `il' parameter, which may further manipulated by the user. But he
	 * must take care not to remove any instruction (handles) that are still
	 * referenced from this object.
	 * 
	 * For example one may not add a local variable and later remove the
	 * instructions it refers to without causing havoc. It is safe however if
	 * you remove that local variable, too.
	 * 
	 * @param access_flags
	 *            access qualifiers
	 * @param return_type
	 *            method type
	 * @param arg_types
	 *            argument types
	 * @param arg_names
	 *            argument names (if this is null, default names will be
	 *            provided for them)
	 * @param method_name
	 *            name of method
	 * @param class_name
	 *            class name containing this method (may be null, if you don't
	 *            care)
	 * @param il
	 *            instruction list associated with this method, may be null only
	 *            for abstract or native methods
	 * @param cp
	 *            constant pool
	 */
	public MethodGen(int access_flags, Type return_type, Type[] arg_types,
			String[] arg_names, String method_name, String class_name,
			InstructionList il, ConstantPoolGen cp) {
		setAccessFlags(access_flags);
		setType(return_type);
		setArgumentTypes(arg_types);
		setArgumentNames(arg_names);
		setName(method_name);
		setClassName(class_name);
		setInstructionList(il);
		setConstantPool(cp);

		boolean abstract_ = isAbstract() || isNative();
		InstructionHandle start = null;
		InstructionHandle end = null;

		if (!abstract_) {
			start = il.getStart();
			end = il.getEnd();

			/*
			 * Add local variables, namely the implicit `this' and the arguments
			 */
			if (!isStatic() && (class_name != null)) { // Instance method ->
														// `this' is
				// local var 0
				addLocalVariable("this", new ObjectType(class_name), start, end);
			}
		}

		if (arg_types != null) {
			int size = arg_types.length;

			for (int i = 0; i < size; i++) {
				if (Type.VOID == arg_types[i]) {
					throw new ClassGenException(
							"'void' is an illegal argument type for a method");
				}
			}

			if (arg_names != null) { // Names for variables provided?
				if (size != arg_names.length)
					throw new ClassGenException(
							"Mismatch in argument array lengths: " + size
									+ " vs. " + arg_names.length);
			} else { // Give them dummy names
				arg_names = new String[size];

				for (int i = 0; i < size; i++)
					arg_names[i] = "arg" + i;

				setArgumentNames(arg_names);
			}

			if (!abstract_) {
				for (int i = 0; i < size; i++) {
					addLocalVariable(arg_names[i], arg_types[i], start, end);
				}
			}
		}
	}

	/*
	 * Additional constructor  
	 * by Ando Saabas
	 */

	public MethodGen(int access_flags, String method_name, String descriptor,
			String class_name, InstructionList il, ConstantPoolGen cp) {
		
		setAccessFlags(access_flags);
		setDescriptor(descriptor);
		setName(method_name);
		setClassName(class_name);
		setInstructionList(il);
		setConstantPool(cp);

		boolean abstract_ = isAbstract() || isNative();
		InstructionHandle start = null;
		InstructionHandle end = null;

		if (!abstract_) {
			start = il.getStart();
			end = il.getEnd();

			/*
			 * Add local variables, namely the implicit `this' and the arguments
			 */
			if (!isStatic() && (class_name != null)) { // Instance method ->
														// `this' is
				// local var 0
				addLocalVariable("this", new ObjectType(class_name), start, end);
			}
		}

	}



	/**
	 * Instantiate from existing method.
	 * 
	 * @param m
	 *            method
	 * @param class_name
	 *            class name containing this method
	 * @param cp
	 *            constant pool
	 */
	public MethodGen(Method m, String class_name, ConstantPoolGen cp) {
		this(
				m.getAccessFlags(),
				Type.getReturnType(m.getSignature()),
				Type.getArgumentTypes(m.getSignature()),
				null /* may be overridden anyway */,
				m.getName(),
				class_name,
				((m.getAccessFlags() & (Constants.ACC_ABSTRACT | Constants.ACC_NATIVE)) == 0) ? new InstructionList(
						m.getCode().getCode())
						: null, cp);

		Attribute[] attributes = m.getAttributes();
		for (int i = 0; i < attributes.length; i++) {
			Attribute a = attributes[i];

			if (a instanceof Code) {
				Code c = (Code) a;
				setMaxStack(c.getMaxStack());
				setMaxLocals(c.getMaxLocals());

				CodeException[] ces = c.getExceptionTable();

				if (ces != null) {
					for (int j = 0; j < ces.length; j++) {
						CodeException ce = ces[j];
						int type = ce.getCatchType();
						ObjectType c_type = null;

						if (type > 0) {
							String cen = m.getConstantPool().getConstantString(
									type, Constants.CONSTANT_Class);
							c_type = new ObjectType(cen);
						}

						int end_pc = ce.getEndPC();
						int length = m.getCode().getCode().length;

						InstructionHandle end;

						if (length == end_pc) { // May happen, because end_pc is
												// exclusive
							end = il.getEnd();
						} else {
							end = il.findHandle(end_pc);
							end = end.getPrev(); // Make it inclusive
						}

						addExceptionHandler(il.findHandle(ce.getStartPC()),
								end, il.findHandle(ce.getHandlerPC()), c_type);
					}
				}

				Attribute[] c_attributes = c.getAttributes();
				for (int j = 0; j < c_attributes.length; j++) {
					a = c_attributes[j];

					if (a instanceof LineNumberTable) {
						LineNumber[] ln = ((LineNumberTable) a)
								.getLineNumberTable();

						for (int k = 0; k < ln.length; k++) {
							LineNumber l = ln[k];
							addLineNumber(il.findHandle(l.getStartPC()), l
									.getLineNumber());
						}
					} else if (a instanceof LocalVariableTable) {
						LocalVariable[] lv = ((LocalVariableTable) a)
								.getLocalVariableTable();

						removeLocalVariables();

						for (int k = 0; k < lv.length; k++) {
							LocalVariable l = lv[k];
							InstructionHandle start = il.findHandle(l
									.getStartPC());
							InstructionHandle end = il.findHandle(l
									.getStartPC()
									+ l.getLength());

							// Repair malformed handles
							if (null == start) {
								start = il.getStart();
							}

							if (null == end) {
								end = il.getEnd();
							}

							addLocalVariable(l.getName(), Type.getType(l
									.getSignature()), l.getIndex(), start, end);
						}
					} else
						addCodeAttribute(a);
				}
			} else if (a instanceof ExceptionTable) {
				String[] names = ((ExceptionTable) a).getExceptionNames();
				for (int j = 0; j < names.length; j++)
					addException(names[j]);
			} else
				addAttribute(a);
		}
	}

	/**
	 * Adds a local variable to this method.
	 * 
	 * @param name
	 *            variable name
	 * @param type
	 *            variable type
	 * @param slot
	 *            the index of the local variable, if type is long or double,
	 *            the next available index is slot+2
	 * @param start
	 *            from where the variable is valid
	 * @param end
	 *            until where the variable is valid
	 * @return new local variable object
	 * @see LocalVariable
	 */
	public LocalVariableGen addLocalVariable(String name, Type type, int slot,
			InstructionHandle start, InstructionHandle end) {
		byte t = type.getType();

		if (t != Constants.T_ADDRESS) {
			int add = type.getSize();

			if (slot + add > max_locals)
				max_locals = slot + add;

			LocalVariableGen l = new LocalVariableGen(slot, name, type, start,
					end);
			int i;

			if ((i = variable_vec.indexOf(l)) >= 0) // Overwrite if necessary
				variable_vec.set(i, l);
			else
				variable_vec.add(l);

			return l;
		} else {
			throw new IllegalArgumentException("Can not use " + type
					+ " as type for local variable");

⌨️ 快捷键说明

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