Rafael Aguilar Rafael Aguilar - 4 months ago 16
Java Question

How to obtain exception message to log it on catch blocks on already existing class with Javassist?

Case:



Try to insert a log method with a String parameter, in this case, with
e.getMessage()
on any catch Block of existing method.

The following snippets can inject a 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);
}
}


Problem



What i can't do is to get the
e.getMessage()
as input parameter to
log(String)
.

Maybe someone could point me in the right direction.

Answer

When you enter a catch block, you will find the exception lying on the stack. Thus, you can extract the message as follows:

  • duplicate the topmost value of the stack which is the exception such that you can call methods of this object without taking away the value for deeper instructions.

  • extract the message from the exception object by calling getMessage virtually on it.

This way, you now have the exception message lying on top of the stack.

Comments