我想知道是否可以将 anAdviceAdapter
与 ASM Tree API 一起使用。
我尝试了以下方法,但是堆空间内存不足。
@Override
public void modify(ClassReader cr, ClassWriter cw) throws Exception
{
ClassNode cn = new ClassNode();
cr.accept(cn, 0);
instrumentTestcases(cn);
cn.accept(cw);
}
@SuppressWarnings("unchecked")
private void instrumentTestcases(ClassNode cn)
{
for (MethodNode methodNode : (List<MethodNode>) cn.methods)
{
if (isTestMethod(methodNode))
{
TestModeAdapter adapter = new TestModeAdapter(methodNode, methodNode.access, methodNode.name, methodNode.desc);
methodNode.accept(adapter);
}
}
}
该类TestModeAdapter
继承AdviceAdapter
并在方法的开头和结尾添加了一条简单的指令。如果我在ClassVisitor
'svisitMethod
方法中使用适配器,则修改成功。
我的代码是否不正确或者适配器只能与核心 API 一起使用?
修改:(TestModeAdapter
扩展AdviceAdapter
)
@Override
protected void onMethodEnter()
{
/**
* InvocationLogger.setMode(LoggingMode.TESTING);
* try
* {
*
*/
insertInstructionToSetMode(LoggingMode.TESTING);
Label l0 = new Label();
this.l1 = new Label();
visitTryCatchBlock(l0, l1, l1, null);
visitLabel(l0);
}
@Override
protected void onMethodExit(int opcode)
{
/**
* }
* finally
* {
* InvocationLogger.setMode(LoggingMode.FRAMING);
* }
*/
/**
* i.e.
*
* InvocationLogger.setMode(LoggingMode.FRAMING);
* }
* catch (Throwable t)
* {
* InvocationLogger.setMode(LoggingMode.FRAMING);
* throw t;
* }
*/
Label l2 = new Label();
visitJumpInsn(GOTO, l2);
visitLabel(this.l1);
visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/Throwable"});
visitVarInsn(ASTORE, 1);
insertInstructionToSetMode(LoggingMode.FRAMING);
visitVarInsn(ALOAD, 1);
visitInsn(ATHROW);
visitLabel(l2);
visitFrame(Opcodes.F_SAME, 0, null, 0, null);
insertInstructionToSetMode(LoggingMode.FRAMING);
}
private void insertInstructionToSetMode(LoggingMode mode)
{
String modeValue = (mode == LoggingMode.TESTING ? FIELD_NAME_TESTING : FIELD_NAME_FRAMING);
visitFieldInsn(Opcodes.GETSTATIC, CP_LOGGING_MODE, modeValue, FIELD_DESC_LOGGING_MODE);
visitMethodInsn(INVOKESTATIC, CP_INVOCATION_LOGGER, METHOD_NAME_SET_MODE, METHOD_DESC_SET_MODE);
}