📄 methodwriter.java
字号:
for ( int i = 0; i < labels.length; ++i ) {
labels[i].put( this,
this.code,
source,
true );
}
}
public void visitLookupSwitchInsn(final Label dflt,
final int keys[],
final Label labels[]) {
if ( this.computeMaxs ) {
// updates current stack size (max stack size unchanged)
--this.stackSize;
// ends current block (with many new successors)
if ( this.currentBlock != null ) {
this.currentBlock.maxStackSize = this.maxStackSize;
addSuccessor( this.stackSize,
dflt );
for ( int i = 0; i < labels.length; ++i ) {
addSuccessor( this.stackSize,
labels[i] );
}
this.currentBlock = null;
}
}
// adds the instruction to the bytecode of the method
final int source = this.code.length;
this.code.putByte( Opcodes.LOOKUPSWITCH );
while ( this.code.length % 4 != 0 ) {
this.code.putByte( 0 );
}
dflt.put( this,
this.code,
source,
true );
this.code.putInt( labels.length );
for ( int i = 0; i < labels.length; ++i ) {
this.code.putInt( keys[i] );
labels[i].put( this,
this.code,
source,
true );
}
}
public void visitMultiANewArrayInsn(final String desc,
final int dims) {
if ( this.computeMaxs ) {
// updates current stack size (max stack size unchanged because
// stack size variation always negative or null)
this.stackSize += 1 - dims;
}
// adds the instruction to the bytecode of the method
this.code.put12( Opcodes.MULTIANEWARRAY,
this.cw.newClass( desc ) ).putByte( dims );
}
public void visitTryCatchBlock(final Label start,
final Label end,
final Label handler,
final String type) {
if ( this.computeMaxs ) {
// pushes handler block onto the stack of blocks to be visited
if ( !handler.pushed ) {
handler.beginStackSize = 1;
handler.pushed = true;
handler.next = this.blockStack;
this.blockStack = handler;
}
}
++this.catchCount;
final Handler h = new Handler();
h.start = start;
h.end = end;
h.handler = handler;
h.desc = type;
h.type = type != null ? this.cw.newClass( type ) : 0;
if ( this.lastHandler == null ) {
this.catchTable = h;
} else {
this.lastHandler.next = h;
}
this.lastHandler = h;
}
public void visitLocalVariable(final String name,
final String desc,
final String signature,
final Label start,
final Label end,
final int index) {
if ( signature != null ) {
if ( this.localVarType == null ) {
this.localVarType = new ByteVector();
}
++this.localVarTypeCount;
this.localVarType.putShort( start.position ).putShort( end.position - start.position ).putShort( this.cw.newUTF8( name ) ).putShort( this.cw.newUTF8( signature ) ).putShort( index );
}
if ( this.localVar == null ) {
this.localVar = new ByteVector();
}
++this.localVarCount;
this.localVar.putShort( start.position ).putShort( end.position - start.position ).putShort( this.cw.newUTF8( name ) ).putShort( this.cw.newUTF8( desc ) ).putShort( index );
}
public void visitLineNumber(final int line,
final Label start) {
if ( this.lineNumber == null ) {
this.lineNumber = new ByteVector();
}
++this.lineNumberCount;
this.lineNumber.putShort( start.position );
this.lineNumber.putShort( line );
}
public void visitMaxs(final int maxStack,
final int maxLocals) {
if ( this.computeMaxs ) {
// true (non relative) max stack size
int max = 0;
/*
* control flow analysis algorithm: while the block stack is not
* empty, pop a block from this stack, update the max stack size,
* compute the true (non relative) begin stack size of the
* successors of this block, and push these successors onto the
* stack (unless they have already been pushed onto the stack).
* Note: by hypothesis, the {@link Label#beginStackSize} of the
* blocks in the block stack are the true (non relative) beginning
* stack sizes of these blocks.
*/
Label stack = this.blockStack;
while ( stack != null ) {
// pops a block from the stack
Label l = stack;
stack = stack.next;
// computes the true (non relative) max stack size of this block
final int start = l.beginStackSize;
final int blockMax = start + l.maxStackSize;
// updates the global max stack size
if ( blockMax > max ) {
max = blockMax;
}
// analyses the successors of the block
Edge b = l.successors;
while ( b != null ) {
l = b.successor;
// if this successor has not already been pushed onto the
// stack...
if ( !l.pushed ) {
// computes the true beginning stack size of this
// successor block
l.beginStackSize = start + b.stackSize;
// pushes this successor onto the stack
l.pushed = true;
l.next = stack;
stack = l;
}
b = b.next;
}
}
this.maxStack = max;
} else {
this.maxStack = maxStack;
this.maxLocals = maxLocals;
}
}
public void visitEnd() {
}
// ------------------------------------------------------------------------
// Utility methods: control flow analysis algorithm
// ------------------------------------------------------------------------
/**
* Computes the size of the arguments and of the return value of a method.
*
* @param desc the descriptor of a method.
* @return the size of the arguments of the method (plus one for the
* implicit this argument), argSize, and the size of its return
* value, retSize, packed into a single int i =
* <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal
* to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
*/
private static int getArgumentsAndReturnSizes(final String desc) {
int n = 1;
int c = 1;
while ( true ) {
char car = desc.charAt( c++ );
if ( car == ')' ) {
car = desc.charAt( c );
return n << 2 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));
} else if ( car == 'L' ) {
while ( desc.charAt( c++ ) != ';' ) {
}
n += 1;
} else if ( car == '[' ) {
while ( (car = desc.charAt( c )) == '[' ) {
++c;
}
if ( car == 'D' || car == 'J' ) {
n -= 1;
}
} else if ( car == 'D' || car == 'J' ) {
n += 2;
} else {
n += 1;
}
}
}
/**
* Adds a successor to the {@link #currentBlock currentBlock} block.
*
* @param stackSize the current (relative) stack size in the current block.
* @param successor the successor block to be added to the current block.
*/
private void addSuccessor(final int stackSize,
final Label successor) {
final Edge b = new Edge();
// initializes the previous Edge object...
b.stackSize = stackSize;
b.successor = successor;
// ...and adds it to the successor list of the currentBlock block
b.next = this.currentBlock.successors;
this.currentBlock.successors = b;
}
// ------------------------------------------------------------------------
// Utility methods: dump bytecode array
// ------------------------------------------------------------------------
/**
* Returns the size of the bytecode of this method.
*
* @return the size of the bytecode of this method.
*/
final int getSize() {
if ( this.classReaderOffset != 0 ) {
return 6 + this.classReaderLength;
}
if ( this.resize ) {
// replaces the temporary jump opcodes introduced by Label.resolve.
resizeInstructions( new int[0],
new int[0],
0 );
}
int size = 8;
if ( this.code.length > 0 ) {
this.cw.newUTF8( "Code" );
size += 18 + this.code.length + 8 * this.catchCount;
if ( this.localVar != null ) {
this.cw.newUTF8( "LocalVariableTable" );
size += 8 + this.localVar.length;
}
if ( this.localVarType != null ) {
this.cw.newUTF8( "LocalVariableTypeTable" );
size += 8 + this.localVarType.length;
}
if ( this.lineNumber != null ) {
this.cw.newUTF8( "LineNumberTable" );
size += 8 + this.lineNumber.length;
}
if ( this.cattrs != null ) {
size += this.cattrs.getSize( this.cw,
this.code.data,
this.code.length,
this.maxStack,
this.maxLocals );
}
}
if ( this.exceptionCount > 0 ) {
this.cw.newUTF8( "Exceptions" );
size += 8 + 2 * this.exceptionCount;
}
if ( (this.access & Opcodes.ACC_SYNTHETIC) != 0 && (this.cw.version & 0xffff) < Opcodes.V1_5 ) {
this.cw.newUTF8( "Synthetic" );
size += 6;
}
if ( (this.access & Opcodes.ACC_DEPRECATED) != 0 ) {
this.cw.newUTF8( "Deprecated" );
size += 6;
}
if ( this.cw.version == Opcodes.V1_4 ) {
if ( (this.access & Opcodes.ACC_VARARGS) != 0 ) {
this.cw.newUTF8( "Varargs" );
size += 6;
}
if ( (this.access & Opcodes.ACC_BRIDGE) != 0 ) {
this.cw.newUTF8( "Bridge" );
size += 6;
}
}
if ( this.signature != null ) {
this.cw.newUTF8( "Signature" );
this.cw.newUTF8( this.signature );
size += 8;
}
if ( this.annd != null ) {
this.cw.newUTF8( "AnnotationDefault" );
size += 6 + this.annd.length;
}
if ( this.anns != null ) {
this.cw.newUTF8( "RuntimeVisibleAnnotations" );
size += 8 + this.anns.getSize();
}
if ( this.ianns != null ) {
this.cw.newUTF8( "RuntimeInvisibleAnnotations" );
size += 8 + this.ianns.getSize();
}
if ( this.panns != null ) {
this.cw.newUTF8( "RuntimeVisibleParameterAnnotations" );
size += 7 + 2 * this.panns.length;
for ( int i = this.panns.length - 1; i >= 0; --i ) {
size += this.panns[i] == null ? 0 : this.panns[i].getSize();
}
}
if ( this.ipanns != null ) {
this.cw.newUTF8( "RuntimeInvisibleParameterAnnotations" );
size += 7 + 2 * this.ipanns.length;
for ( int i = this.ipanns.length - 1; i >= 0; --i ) {
size += this.ipanns[i] == null ? 0 : this.ipanns[i].getSize();
}
}
if ( this.attrs != null ) {
size += this.attrs.getSize( this.cw,
null,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -