0

我想知道是否可以将 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);
}
4

0 回答 0