📄 methodgen.java
字号:
}
}
/**
* Adds a local variable to this method and assigns an index automatically.
*
* @param name
* variable name
* @param type
* variable type
* @param start
* from where the variable is valid, if this is null, it is valid
* from the start
* @param end
* until where the variable is valid, if this is null, it is
* valid to the end
* @return new local variable object
* @see LocalVariable
*/
public LocalVariableGen addLocalVariable(String name, Type type,
InstructionHandle start, InstructionHandle end) {
return addLocalVariable(name, type, max_locals, start, end);
}
/**
* Remove a local variable, its slot will not be reused, if you do not use
* addLocalVariable with an explicit index argument.
*/
public void removeLocalVariable(LocalVariableGen l) {
variable_vec.remove(l);
}
/**
* Remove all local variables.
*/
public void removeLocalVariables() {
variable_vec.clear();
}
/**
* Sort local variables by index
*/
private static final void sort(LocalVariableGen[] vars, int l, int r) {
int i = l, j = r;
int m = vars[(l + r) / 2].getIndex();
LocalVariableGen h;
do {
while (vars[i].getIndex() < m)
i++;
while (m < vars[j].getIndex())
j--;
if (i <= j) {
h = vars[i];
vars[i] = vars[j];
vars[j] = h; // Swap elements
i++;
j--;
}
} while (i <= j);
if (l < j)
sort(vars, l, j);
if (i < r)
sort(vars, i, r);
}
/*
* If the range of the variable has not been set yet, it will be set to be
* valid from the start to the end of the instruction list.
*
* @return array of declared local variables sorted by index
*/
public LocalVariableGen[] getLocalVariables() {
int size = variable_vec.size();
LocalVariableGen[] lg = new LocalVariableGen[size];
variable_vec.toArray(lg);
for (int i = 0; i < size; i++) {
if (lg[i].getStart() == null)
lg[i].setStart(il.getStart());
if (lg[i].getEnd() == null)
lg[i].setEnd(il.getEnd());
}
if (size > 1)
sort(lg, 0, size - 1);
return lg;
}
/**
* @return `LocalVariableTable' attribute of all the local variables of this
* method.
*/
public LocalVariableTable getLocalVariableTable(ConstantPoolGen cp) {
LocalVariableGen[] lg = getLocalVariables();
int size = lg.length;
LocalVariable[] lv = new LocalVariable[size];
for (int i = 0; i < size; i++)
lv[i] = lg[i].getLocalVariable(cp);
return new LocalVariableTable(cp.addUtf8("LocalVariableTable"),
2 + lv.length * 10, lv, cp.getConstantPool());
}
/**
* Give an instruction a line number corresponding to the source code line.
*
* @param ih
* instruction to tag
* @return new line number object
* @see LineNumber
*/
public LineNumberGen addLineNumber(InstructionHandle ih, int src_line) {
LineNumberGen l = new LineNumberGen(ih, src_line);
line_number_vec.add(l);
return l;
}
/**
* Remove a line number.
*/
public void removeLineNumber(LineNumberGen l) {
line_number_vec.remove(l);
}
/**
* Remove all line numbers.
*/
public void removeLineNumbers() {
line_number_vec.clear();
}
/*
* @return array of line numbers
*/
public LineNumberGen[] getLineNumbers() {
LineNumberGen[] lg = new LineNumberGen[line_number_vec.size()];
line_number_vec.toArray(lg);
return lg;
}
/**
* @return `LineNumberTable' attribute of all the local variables of this
* method.
*/
public LineNumberTable getLineNumberTable(ConstantPoolGen cp) {
int size = line_number_vec.size();
LineNumber[] ln = new LineNumber[size];
try {
for (int i = 0; i < size; i++)
ln[i] = ((LineNumberGen) line_number_vec.get(i))
.getLineNumber();
} catch (ArrayIndexOutOfBoundsException e) {
} // Never occurs
return new LineNumberTable(cp.addUtf8("LineNumberTable"),
2 + ln.length * 4, ln, cp.getConstantPool());
}
/**
* Add an exception handler, i.e., specify region where a handler is active
* and an instruction where the actual handling is done.
*
* @param start_pc
* Start of region (inclusive)
* @param end_pc
* End of region (inclusive)
* @param handler_pc
* Where handling is done
* @param catch_type
* class type of handled exception or null if any exception is
* handled
* @return new exception handler object
*/
public CodeExceptionGen addExceptionHandler(InstructionHandle start_pc,
InstructionHandle end_pc, InstructionHandle handler_pc,
ObjectType catch_type) {
if ((start_pc == null) || (end_pc == null) || (handler_pc == null))
throw new ClassGenException(
"Exception handler target is null instruction");
CodeExceptionGen c = new CodeExceptionGen(start_pc, end_pc, handler_pc,
catch_type);
exception_vec.add(c);
return c;
}
/**
* Remove an exception handler.
*/
public void removeExceptionHandler(CodeExceptionGen c) {
exception_vec.remove(c);
}
/**
* Remove all line numbers.
*/
public void removeExceptionHandlers() {
exception_vec.clear();
}
/*
* @return array of declared exception handlers
*/
public CodeExceptionGen[] getExceptionHandlers() {
CodeExceptionGen[] cg = new CodeExceptionGen[exception_vec.size()];
exception_vec.toArray(cg);
return cg;
}
/**
* @return code exceptions for `Code' attribute
*/
private CodeException[] getCodeExceptions() {
int size = exception_vec.size();
CodeException[] c_exc = new CodeException[size];
try {
for (int i = 0; i < size; i++) {
CodeExceptionGen c = (CodeExceptionGen) exception_vec.get(i);
c_exc[i] = c.getCodeException(cp);
}
} catch (ArrayIndexOutOfBoundsException e) {
}
return c_exc;
}
/**
* Add an exception possibly thrown by this method.
*
* @param class_name
* (fully qualified) name of exception
*/
public void addException(String class_name) {
throws_vec.add(class_name);
}
/**
* Remove an exception.
*/
public void removeException(String c) {
throws_vec.remove(c);
}
/**
* Remove all exceptions.
*/
public void removeExceptions() {
throws_vec.clear();
}
/*
* @return array of thrown exceptions
*/
public String[] getExceptions() {
String[] e = new String[throws_vec.size()];
throws_vec.toArray(e);
return e;
}
/**
* @return `Exceptions' attribute of all the exceptions thrown by this
* method.
*/
private ExceptionTable getExceptionTable(ConstantPoolGen cp) {
int size = throws_vec.size();
int[] ex = new int[size];
try {
for (int i = 0; i < size; i++)
ex[i] = cp.addClass((String) throws_vec.get(i));
} catch (ArrayIndexOutOfBoundsException e) {
}
return new ExceptionTable(cp.addUtf8("Exceptions"), 2 + 2 * size, ex,
cp.getConstantPool());
}
/**
* Add an attribute to the code. Currently, the JVM knows about the
* LineNumberTable, LocalVariableTable and StackMap attributes, where the
* former two will be generated automatically and the latter is used for the
* MIDP only. Other attributes will be ignored by the JVM but do no harm.
*
* @param a
* attribute to be added
*/
public void addCodeAttribute(Attribute a) {
code_attrs_vec.add(a);
}
/**
* Remove a code attribute.
*/
public void removeCodeAttribute(Attribute a) {
code_attrs_vec.remove(a);
}
/**
* Remove all code attributes.
*/
public void removeCodeAttributes() {
code_attrs_vec.clear();
}
/**
* @return all attributes of this method.
*/
public Attribute[] getCodeAttributes() {
Attribute[] attributes = new Attribute[code_attrs_vec.size()];
code_attrs_vec.toArray(attributes);
return attributes;
}
/**
* Get method object. Never forget to call setMaxStack() or
* setMaxStack(max), respectively, before calling this method (the same
* applies for max locals).
*
* @return method object
*/
public Method getMethod() {
String signature;
if (descriptor == null) {
signature = getSignature();
}else {
signature = descriptor;
}
int name_index = cp.addUtf8(name);
int signature_index = cp.addUtf8(signature);
/*
* Also updates positions of instructions, i.e., their indices
*/
byte[] byte_code = null;
if (il != null)
byte_code = il.getByteCode();
LineNumberTable lnt = null;
LocalVariableTable lvt = null;
/*
* Create LocalVariableTable and LineNumberTable attributes (for
* debuggers, e.g.)
*/
if ((variable_vec.size() > 0) && !strip_attributes)
addCodeAttribute(lvt = getLocalVariableTable(cp));
if ((line_number_vec.size() > 0) && !strip_attributes)
addCodeAttribute(lnt = getLineNumberTable(cp));
Attribute[] code_attrs = getCodeAttributes();
/*
* Each attribute causes 6 additional header bytes
*/
int attrs_len = 0;
for (int i = 0; i < code_attrs.length; i++)
attrs_len += (code_attrs[i].getLength() + 6);
CodeException[] c_exc = getCodeExceptions();
int exc_len = c_exc.length * 8; // Every entry takes 8 bytes
Code code = null;
if ((il != null) && !isAbstract()) {
// Remove any stale code attribute
Attribute[] attributes = getAttributes();
for (int i = 0; i < attributes.length; i++) {
Attribute a = attributes[i];
if (a instanceof Code)
removeAttribute(a);
}
code = new Code(cp.addUtf8("Code"), 8 + byte_code.length + // prologue
// byte
// code
2 + exc_len + // exceptions
2 + attrs_len, // attributes
max_stack, max_locals, byte_code, c_exc, code_attrs, cp
.getConstantPool());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -