Java forge a stack trace.

Forging a stack trace in java

The java.lang.Throwable.setStackTrace() method sets the stack trace elements that will be returned by getStackTrace() and printed by printStackTrace() and related methods.
The signature of the method is below.
public void setStackTrace(StackTraceElement[] stackTrace)
This method can be used to modify the actual stack trace.

When do you want to modify the original stack trace?

There are certain scenarios when the application developer decides to append, prepend or curtail the original stack trace.
  • Java RMI implementation constructs a stack trace by prepending the remote stack trace.
  • Some libraries merge the stack traces from different sources which are all can be a reason for current stack trace.
  • Sometimes you do not want the larger stack trace information to go into logs.
 For example an application which handles validation errors by means of java exception chaining will log the validation error and print the stack trace also in the logs. All we need is just the error message with code and not the stack trace. In this case we can set stack trace to print just the first one line instead the complete chain.

Example code


public class Test {

public static void main(String[] args) throws SomeException {

   tell();
}

private static void tell() throws SomeException {
   SomeException ex = new SomeException("Error during this call");
   System.out.println("*************************** Original stack trace *************************");
   ex.printStackTrace();
 //let it wait for a while to avoid ouputstream clashing
  try {
     Thread.sleep(1000);
 } catch (InterruptedException e) { }
 System.out.println("Stack trace tweaked!");
 ex.setStackTrace(new StackTraceElement[] { new StackTraceElement("MyTweakedClass", "SomeMethod", "SomeFile", 1)  });

//ex.fillInStackTrace(); // This will reset the stack trace to original.
 throw ex;
}

static class SomeException extends Throwable {
private static final long serialVersionUID = 1L;
  public SomeException(String msg) {
     super(msg);
    }
  }
}

Output


*************************** Original stack trace *************************

test.Test$SomeException: Error during this call
at test.Test.tell(Test.java:17)
at test.Test.main(Test.java:13)
Stack trace tweaked!
Exception in thread "main" test.Test$SomeException: Error during this call
at MyTweakedClass.SomeMethod(SomeFile:1)

How to get the original stack trace back?

To get the original stack trace back, call the fillInStackTrace() method on the exception. After un-commenting the ex.fillInStackTrace() following is the output.

After ex.fillInStackTrace()


*************************** Original stack trace *************************
test.Test$SomeException: Error during this call
at test.Test.tell(Test.java:17)
at test.Test.main(Test.java:13)

Stack trace tweaked!
Exception in thread "main" test.Test$SomeException: Error during this call
at test.Test.tell(Test.java:28)
at test.Test.main(Test.java:13)
After fillInStackTrace() method called, the original is stack trace is preserved.





Comments

Post a Comment

Popular posts from this blog

Log4j multiple WAR files in single EAR configuration

Java NIO2 - Watching a directory for changes. FileWatcherService.

Ubuntu / kubuntu - Laptop key board cursor jumping issue