CodeAttributepublic class CodeAttribute extends ClassAttribute Subtype of ClassAttribute which describes the "Code" attribute
associated with a method. |
Fields Summary |
---|
public static final String | expectedAttrName | private byte[] | theDataBytes | private int | maxStack | private int | maxLocals | private byte[] | theCodeBytes | private Insn | theCode | private ExceptionTable | exceptionTable | private AttributeVector | codeAttributes | CodeEnv | codeEnv |
Constructors Summary |
---|
public CodeAttribute(ConstUtf8 attrName, int maxStack, int maxLocals, Insn code, ExceptionTable excTable, AttributeVector codeAttrs)Constructs a CodeAttribute object for construction from scratch
this(attrName, maxStack, maxLocals, code, null, /* byteCodes */
excTable, codeAttrs, null /* CodeEnv */ );
| public CodeAttribute(ConstUtf8 attrName, int maxStack, int maxLocals, Insn code, byte[] codeBytes, ExceptionTable excTable, AttributeVector codeAttrs, CodeEnv codeEnv)Constructs a CodeAttribute object
super(attrName);
this.maxStack = maxStack;
this.maxLocals = maxLocals;
theCode = code;
theCodeBytes = codeBytes;
exceptionTable = excTable;
codeAttributes = codeAttrs;
this.codeEnv = codeEnv;
| public CodeAttribute(ConstUtf8 attrName, byte[] dataBytes, CodeEnv codeEnv)Constructs a CodeAttribute object for later disassembly
super(attrName);
this.theDataBytes = dataBytes;
this.codeEnv = codeEnv;
|
Methods Summary |
---|
public AttributeVector | attributes()Return the attributes which apply to this code
makeValid();
return codeAttributes;
| private void | buildInstructionBytes()Derive the instruction byte codes from the instruction list
This should also recompute stack and variables but for now we
assume that this isn't needed
if (theCode != null) {
/* Make sure instructions have correct offsets */
int size = resolveOffsets();
theCodeBytes = new byte[size];
Insn insn = theCode;
int index = 0;
while (insn != null) {
index = insn.store(theCodeBytes, index);
insn = insn.next();
}
}
| private void | buildInstructions(CodeEnv codeEnv)Derive the instruction list from the instruction byte codes
if (theCodeBytes != null) {
InsnReadEnv insnEnv = new InsnReadEnv(theCodeBytes, codeEnv);
theCode = insnEnv.getTarget(0);
Insn currInsn = theCode;
/* First, create instructions */
while (insnEnv.more()) {
Insn newInsn = Insn.read(insnEnv);
currInsn.setNext(newInsn);
currInsn = newInsn;
}
/* Now, insert targets */
InsnTarget targ;
currInsn = theCode;
Insn prevInsn = null;
while (currInsn != null) {
int off = currInsn.offset();
/* We always insert a target a 0 to start so ignore that one */
if (off > 0) {
targ = codeEnv.findTarget(off);
if (targ != null)
prevInsn.setNext(targ);
}
prevInsn = currInsn;
currInsn = currInsn.next();
}
/* And follow up with a final target if needed */
targ = codeEnv.findTarget(insnEnv.currentPC());
if (targ != null)
prevInsn.setNext(targ);
}
| public byte[] | byteCodes()Return the java VM byte code sequence for this method - null for
native and abstract methods
makeValid();
return theCodeBytes;
| int | codeSize()
makeValid();
return theCodeBytes.length;
| public ExceptionTable | exceptionHandlers()Return the exception ranges and handlers which apply to the code in
this method.
makeValid();
return exceptionTable;
| public int | localsUsed()Return the maximum number of local variables used by this method
makeValid();
return maxLocals;
| private void | makeValid()If theDataBytes is non-null, disassemble this code attribute
from the data bytes.
if (theDataBytes != null) {
DataInputStream dis = new DataInputStream(
new ByteArrayInputStream(theDataBytes));
try {
maxStack = dis.readUnsignedShort();
maxLocals = dis.readUnsignedShort();
int codeLength = dis.readInt();
theCodeBytes = new byte[codeLength];
dis.readFully(theCodeBytes);
exceptionTable = ExceptionTable.read(dis, codeEnv);
codeAttributes = AttributeVector.readAttributes(dis, codeEnv);
} catch (java.io.IOException ioe) {
ClassFormatError cfe = new ClassFormatError(
"IOException while reading code attribute");//NOI18N
cfe.initCause(ioe);
throw cfe;
}
theDataBytes = null;
}
| void | print(java.io.PrintStream out, int indent)
makeValid();
ClassPrint.spaces(out, indent);
out.print("Code:");//NOI18N
out.print(" max_stack = " + Integer.toString(maxStack));//NOI18N
out.print(" max_locals = " + Integer.toString(maxLocals));//NOI18N
out.println(" Exceptions:");//NOI18N
exceptionTable.print(out, indent+2);
ClassPrint.spaces(out, indent);
out.println("Code Attributes:");//NOI18N
codeAttributes.print(out, indent+2);
Insn insn = theCode();
if (insn != null) {
ClassPrint.spaces(out, indent);
out.println("Instructions:");//NOI18N
while (insn != null) {
insn.print(out, indent+2);
insn = insn.next();
}
}
| static com.sun.jdo.api.persistence.enhancer.classfile.CodeAttribute | read(ConstUtf8 attrName, java.io.DataInputStream data, ConstantPool pool)
int maxStack = data.readUnsignedShort();
int maxLocals = data.readUnsignedShort();
int codeLength = data.readInt();
byte codeBytes[] = new byte[codeLength];
data.readFully(codeBytes);
Insn code = null;
CodeEnv codeEnv = new CodeEnv(pool);
ExceptionTable excTable = ExceptionTable.read(data, codeEnv);
AttributeVector codeAttrs =
AttributeVector.readAttributes(data, codeEnv);
return new CodeAttribute(attrName, maxStack, maxLocals, code, codeBytes,
excTable, codeAttrs, codeEnv);
| static com.sun.jdo.api.persistence.enhancer.classfile.CodeAttribute | read(ConstUtf8 attrName, int attrLength, java.io.DataInputStream data, ConstantPool pool)
byte dataBytes[] = new byte[attrLength];
data.readFully(dataBytes);
return new CodeAttribute(attrName, dataBytes, new CodeEnv(pool));
| private int | resolveOffsets()Assign offsets to instructions and return the number of bytes.
theCode must be non-null.
Insn insn = theCode;
int currPC = 0;
while (insn != null) {
currPC = insn.resolveOffset(currPC);
insn = insn.next();
}
return currPC;
| public void | setLocalsUsed(int used)Set the maximum number of local variables used by this method
makeValid();
maxLocals = used;
| public void | setStackUsed(int used)Set the maximum number of stack entries used by this method
makeValid();
maxStack = used;
| public void | setTheCode(Insn insn)Install the instruction sequence for this method - the byte code array
is later updated.
makeValid();
if (insn != null && insn.opcode() != Insn.opc_target)
throw new InsnError(
"The initial instruction in all methods must be a target");//NOI18N
theCode = insn;
| public int | stackUsed()Return the maximum number of stack entries used by this method
/* public accessors */
makeValid();
return maxStack;
| public Insn | theCode()Return the instruction sequence for this method - initially derived
from the byte code array, but may later be modified
makeValid();
if (theCode == null && codeEnv != null) {
buildInstructions(codeEnv);
}
return theCode;
| void | write(java.io.DataOutputStream out)
out.writeShort(attrName().getIndex());
if (theDataBytes == null) {
buildInstructionBytes();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream tmpOut = new DataOutputStream(baos);
tmpOut.writeShort(maxStack);
tmpOut.writeShort(maxLocals);
tmpOut.writeInt(theCodeBytes.length);
tmpOut.write(theCodeBytes, 0, theCodeBytes.length);
exceptionTable.write(tmpOut);
codeAttributes.write(tmpOut);
tmpOut.flush();
byte tmpBytes[] = baos.toByteArray();
out.writeInt(tmpBytes.length);
out.write(tmpBytes, 0, tmpBytes.length);
} else {
out.writeInt(theDataBytes.length);
out.write(theDataBytes, 0, theDataBytes.length);
}
|
|