Using Instrumentation to record unhandled exception
aspectj, instrumentation, java, javaagents
Solution
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 code
GETSTATIC 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.
Problem
I was trying to debug java application using instrumentation. The problem with current system are - Hardly written any log statements - Poor exception handling This made very difficult to trace root cause of broken functionality. To handle the situation I have developed tool,java agent using `Instrumentation` API , and I was able to inject log statements and half of the problem solved. But the next problem is to recording the Exception. I want to extend my tool record every exception thrown during the execution of the application. I tried injecting 'try-catch' block using `javaassist` API for methods (using `addCatch`, `insertBefore` and `insertAfter`), and it is effective certain extent. ``` public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (className.startsWith("com/alu/")) { return insertLog(className, classBeingRedefined, classfileBuffer); } if(className.endsWith("Exception")){ System.out.println("============= exception occured "+className); } ``` Here `inserLog(..)` method will inject necessary log statement and works fine,but when there is any Exception it doesn't come to transformer. But the problem is some of the method handles exception inside ( even with out log/sysout). eg: ``` try { if(search.equals("Category")){ //do operation } } catch (Exception e) { } ``` This code eats `NullPointerException` when value of `search` is null, I never know this exception and application fail for some thing else. Ultimately what I want is a mechanism to record any exception thrown by application. following details are to be captured - Exception Type - Excpetion Stacktrace - Method and class name I know there is API `Thread.setDefaultUncaughtExceptionHandler`, but not sure how it use with java instrumentation. I don't have any source access the application. [update 1] I found below link tells to use `retransformation` , I will give a try and update How to instrument java system classes? Any guidance would be greatly helpful.