如何获取异常消息以使用Javassist将其记录在已存在的类上的catch块上?

时间:2014-06-25 14:36:34

标签: java instrumentation javassist

案例:

尝试在现有方法的任何catch块上插入带有String参数的日志方法,在本例中为e.getMessage()

以下代码段可以注入String。

...
CtMethod log =   CtNewMethod.make("public void log(String s){ " +
                    " System.out.println(\"Hello from injected log method \" + s); " +
                    "}",
                    ct);
ct.addMethod(log);

...
ControlFlow cf = new ControlFlow(m);
Block blocks[] = cf.basicBlocks();
for(Block block : blocks){
    Catcher catchers[] = block.catchers();
    ArrayList<Catcher> catchersList = new ArrayList<Catcher>(Arrays.asList(catchers));
    Collections.reverse(catchersList);
    for (Catcher catcher : catchersList){
        Block catchBlock = catcher.block();
        int pos = catchBlock.position();

        CodeIterator itr = m.getMethodInfo().getCodeAttribute().iterator();

        Bytecode code = new Bytecode(m.getMethodInfo().getConstPool(), 0, 0);

        code.addAload(0);
        code.addLdc("LogParameter");
        code.addInvokevirtual(ct,"log",log.getMethodInfo().getDescriptor());
        code.addGap(2);
        int n = itr.insertAt(pos,code.get());

        m.getMethodInfo().rebuildStackMapForME(cp);
    }
}

问题

我无法将e.getMessage()作为输入参数log(String)

也许有人可以指出我正确的方向。

1 个答案:

答案 0 :(得分:1)

当您输入catch块时,您会发现堆栈上存在异常。因此,您可以按如下方式提取消息:

  • 复制堆栈的最高值,这是一个例外,这样您就可以调用此对象的方法而不会删除更深层指令的值。

  • 通过虚拟调用getMessage来从异常对象中提取消息。

这样,您现在可以在堆栈顶部放置异常消息。