📄 adviceadapter.java
字号:
case IRETURN :
case FRETURN :
case ARETURN :
case LRETURN :
case DRETURN :
case ATHROW :
onMethodExit( opcode );
break;
}
}
this.mv.visitInsn( opcode );
}
public void visitVarInsn(final int opcode,
final int var) {
super.visitVarInsn( opcode,
var );
if ( this.constructor ) {
switch ( opcode ) {
case ILOAD :
case FLOAD :
pushValue( AdviceAdapter.OTHER );
break;
case LLOAD :
case DLOAD :
pushValue( AdviceAdapter.OTHER );
pushValue( AdviceAdapter.OTHER );
break;
case ALOAD :
pushValue( var == 0 ? AdviceAdapter.THIS : AdviceAdapter.OTHER );
break;
case ASTORE :
case ISTORE :
case FSTORE :
popValue();
break;
case LSTORE :
case DSTORE :
popValue();
popValue();
break;
}
}
}
public void visitFieldInsn(final int opcode,
final String owner,
final String name,
final String desc) {
this.mv.visitFieldInsn( opcode,
owner,
name,
desc );
if ( this.constructor ) {
final char c = desc.charAt( 0 );
final boolean longOrDouble = c == 'J' || c == 'D';
switch ( opcode ) {
case GETSTATIC :
pushValue( AdviceAdapter.OTHER );
if ( longOrDouble ) {
pushValue( AdviceAdapter.OTHER );
}
break;
case PUTSTATIC :
popValue();
if ( longOrDouble ) {
popValue();
}
break;
case PUTFIELD :
popValue();
if ( longOrDouble ) {
popValue();
popValue();
}
break;
// case GETFIELD:
default :
if ( longOrDouble ) {
pushValue( AdviceAdapter.OTHER );
}
}
}
}
public void visitIntInsn(final int opcode,
final int operand) {
this.mv.visitIntInsn( opcode,
operand );
if ( this.constructor ) {
switch ( opcode ) {
case BIPUSH :
case SIPUSH :
pushValue( AdviceAdapter.OTHER );
}
}
}
public void visitLdcInsn(final Object cst) {
this.mv.visitLdcInsn( cst );
if ( this.constructor ) {
pushValue( AdviceAdapter.OTHER );
if ( cst instanceof Double || cst instanceof Long ) {
pushValue( AdviceAdapter.OTHER );
}
}
}
public void visitMultiANewArrayInsn(final String desc,
final int dims) {
this.mv.visitMultiANewArrayInsn( desc,
dims );
if ( this.constructor ) {
for ( int i = 0; i < dims; i++ ) {
popValue();
}
pushValue( AdviceAdapter.OTHER );
}
}
public void visitTypeInsn(final int opcode,
final String name) {
this.mv.visitTypeInsn( opcode,
name );
// ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack
if ( this.constructor && opcode == Opcodes.NEW ) {
pushValue( AdviceAdapter.OTHER );
}
}
public void visitMethodInsn(final int opcode,
final String owner,
final String name,
final String desc) {
this.mv.visitMethodInsn( opcode,
owner,
name,
desc );
if ( this.constructor ) {
final Type[] types = Type.getArgumentTypes( desc );
for ( int i = 0; i < types.length; i++ ) {
popValue();
if ( types[i].getSize() == 2 ) {
popValue();
}
}
switch ( opcode ) {
// case INVOKESTATIC:
// break;
case INVOKEINTERFACE :
case INVOKEVIRTUAL :
popValue(); // objectref
break;
case INVOKESPECIAL :
final Object type = popValue(); // objectref
if ( type == AdviceAdapter.THIS && !this.superInitialized ) {
onMethodEnter();
this.superInitialized = true;
// once super has been initialized it is no longer
// necessary to keep track of stack state
this.constructor = false;
}
break;
}
final Type returnType = Type.getReturnType( desc );
if ( returnType != Type.VOID_TYPE ) {
pushValue( AdviceAdapter.OTHER );
if ( returnType.getSize() == 2 ) {
pushValue( AdviceAdapter.OTHER );
}
}
}
}
public void visitJumpInsn(final int opcode,
final Label label) {
this.mv.visitJumpInsn( opcode,
label );
if ( this.constructor ) {
switch ( opcode ) {
case IFEQ :
case IFNE :
case IFLT :
case IFGE :
case IFGT :
case IFLE :
case IFNULL :
case IFNONNULL :
popValue();
break;
case IF_ICMPEQ :
case IF_ICMPNE :
case IF_ICMPLT :
case IF_ICMPGE :
case IF_ICMPGT :
case IF_ICMPLE :
case IF_ACMPEQ :
case IF_ACMPNE :
popValue();
popValue();
break;
case JSR :
pushValue( AdviceAdapter.OTHER );
break;
}
addBranch( label );
}
}
public void visitLookupSwitchInsn(final Label dflt,
final int[] keys,
final Label[] labels) {
this.mv.visitLookupSwitchInsn( dflt,
keys,
labels );
if ( this.constructor ) {
popValue();
addBranches( dflt,
labels );
}
}
public void visitTableSwitchInsn(final int min,
final int max,
final Label dflt,
final Label[] labels) {
this.mv.visitTableSwitchInsn( min,
max,
dflt,
labels );
if ( this.constructor ) {
popValue();
addBranches( dflt,
labels );
}
}
private void addBranches(final Label dflt,
final Label[] labels) {
addBranch( dflt );
for ( int i = 0; i < labels.length; i++ ) {
addBranch( labels[i] );
}
}
private void addBranch(final Label label) {
if ( this.branches.containsKey( label ) ) {
return;
}
final ArrayList frame = new ArrayList();
frame.addAll( this.stackFrame );
this.branches.put( label,
frame );
}
private Object popValue() {
return this.stackFrame.remove( this.stackFrame.size() - 1 );
}
private Object peekValue() {
return this.stackFrame.get( this.stackFrame.size() - 1 );
}
private void pushValue(final Object o) {
this.stackFrame.add( o );
}
/**
* Called at the beginning of the method or after super
* class class call in the constructor.
* <br><br>
*
* <i>Custom code can use or change all the local variables,
* but should not change state of the stack.</i>
*/
protected abstract void onMethodEnter();
/**
* Called before explicit exit from the method using either
* return or throw. Top element on the stack contains the
* return value or exception instance. For example:
*
* <pre>
* public void onMethodExit(int opcode) {
* if(opcode==RETURN) {
* visitInsn(ACONST_NULL);
* } else if(opcode==ARETURN || opcode==ATHROW) {
* dup();
* } else {
* if(opcode==LRETURN || opcode==DRETURN) {
* dup2();
* } else {
* dup();
* }
* box(Type.getReturnType(this.methodDesc));
* }
* visitIntInsn(SIPUSH, opcode);
* visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
* }
*
* // an actual call back method
* public static void onExit(int opcode, Object param) {
* ...
* </pre>
*
* <br><br>
*
* <i>Custom code can use or change all the local variables,
* but should not change state of the stack.</i>
*
* @param opcode one of the RETURN, IRETURN, FRETURN,
* ARETURN, LRETURN, DRETURN or ATHROW
*
*/
protected abstract void onMethodExit(int opcode);
// TODO onException, onMethodCall
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -