📄 methodgen.java
字号:
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 + -