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