I think you should use ASM to manipulate bytecode directly. Here is algoritms:
- Visit all try/catch blocks (see visitTryCatchBlock) and save all
handler
labels - Visit instructions until one of the
handler
labels met. -
After
handler
label insert logging codeGETSTATIC java/lang/System out LDC "exception X occured" INVOKEVIRTUAL java/io/PrintStream println (java/lang/String)V
And ensure that your javaagent works fine. Checkt that your MANIFEST.MF file contains proper premain
declaration and enables class transformation.
About your current code. Here
if (className.startsWith("com/alu/")) {
return insertLog(className, classBeingRedefined, classfileBuffer);
}
you transforming classes inside particular package. That classes contain code that, in particular, throw exceptions.
And here
if(className.endsWith("Exception")){
System.out.println("============= exception occured "+className);
}
you log of class being retransfomed when it is first loaded by JVM, when its name ends with "Exception"
. Not when exception occured. But transforming exception is useless itself. So I guess you should proceed like this:
if (className.startsWith("com/alu/")) {
System.out.println("============= class transformed "+ className);
return insertLog(className, classBeingRedefined, classfileBuffer);
}
So you could know that your agent at least works.
You have to deal with code like this
try {
if(search.equals("Category")){
//do operation
}
} catch (Exception e) {
}
where exceptions are swallowed. You transform methods that they will be like this:
try {
try {
if(search.equals("Category")){
//do operation
}
} catch (Exception e) {
}
} catch (Exception e) {
e.printStackTrace();
}
Of course, when exception was swallowed by the first catch
, the second one never cathes it. Instead, you should transform existing catch
blocks themself, to get the following code:
try {
if(search.equals("Category")){
//do operation
}
} catch (Exception e) {
e.printStackTrace();
}
Above I shown you how to achieve this with ASM.