How do I in java add a stacktrace to my debugging printout - java

What's the easiest way to print a stacktrace from a debugging printout? Often during testing you would like to know the callstack leading up to the situation provoking a debug message.

If you're using log4j
Exception e = new Exception();
log.error("error here", e);
will print the stacktrace to your log.

Thread.dumpStack();

If you want to save the stack trace into a String you can do this;
String exception = "";
for (StackTraceElement element : e.getStackTrace())
exception += element.toString() + "\n";
Where e is, obviously, an exception.
Besides, it sounds very weird to autogenerate an own Exception just to find get a stack trace for a debug. Get Eclipse and use it's debug mode, it's really awesome.

Just creating an arbitrary exception does the trick for me:
System.out.println("Oops, the bad thing happened");
new IllegalStateException().printStackTrace();

As well as what #jjnguy said, if you don't have an exception, you can also call Thread.getStackTrace().

You should be catching the exception in a try-catch block.
e.getStackTrace();
That returns StackTraceElement[] that you can then interpret.
Also:
e.printStackTrace()
will...print the stacktrace.

To simply print the current stack trace to stderr, you can call:
Thread.dumpStack();
which itself just calls:
new Exception("Stack trace").printStackTrace();
To output to stdout rather than stderr, pass System.out to printStackTrace():
new Exception("Stack trace").printStackTrace(System.out);

Just because I needed it myself:
As inspired by answer How do I find the caller of a method using stacktrace or reflection? , you can retrieve the call stack using
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace()
Then you process and print/log whatever you are interested in. More work than using Thread.dumpStack(), but more flexible.

Related

When I catch the Exception and log it, the log just displays The Exception Name, not the Exception Stack

Though the log in server, the log display the Exception Name : NullPointerException, but the Exception Stack not display so that I could't find the source of the error.
Please tell me why the log did't display the Exception stack, and how could I right it ? And the log system is log4j system
try {
// ... function called
} catch (Throwable t) {
log.error("the Exception is : ", t);
}
The error log just displays : the Exception is : java.lang.NullPointerException
Use logger.catching(t) or add t.getStackTrace() as parameter.
If you use logger.error(<A String>, <A Object>) log4j will simply use the toString method of the Object.
Are you using Log4j? If yes, you are using the correct two parameter method actually. It should print the stack trace as well. Refer docs for error- http://logging.apache.org/log4j/1.2/index.html
If you still want the stack trace otherwise try this.
StringWriter sw = new StringWriter();
ex.printStackTrace(new PrintWriter(sw));
String stacktrace = sw.toString();
log.error(stacktrace);
But I would advise you to stick to your implementation.

why it is not recommended to use e.printstacktrace() by sonar?

i recently started using sonar as code review tool.
When i analysed my code running sonar,
it reflected printing stack trace as violation of java coding standard.
As an alternative to stack trace, I tried:
e.getcause()
but this did not clear the exception as done by stack trace
Error handling can be tricky in any environment, java included. I haven't used sonar, but I can comment on general good practices for java error handling.
e.printStackTrace() is generally discouraged because it just prints out the stack trace to standard error. Because of this you can't really control where this output goes.
The better thing to do is to use a logging framework (logback, slf4j, java.util.logging, log4j, etc) because then you can control where the errors are logged to and what the log retention policy is.
And generally you'll want to catch the exception and if it's unexpected behavior, log it and either throw a new exception (probably specific to your application) or do whatever you have to do to continue operating gracefully.
If you're using java.util.logging, you can do something like the following:
class YourClass
{
Logger logger = Logger.getLogger(YourClass.class.getName());
...
public void someMethod() throws YourException
{
try
{
// your code here
} catch (NullPointerException e)
{
String message = "Unexpected NullPointerException in processing!";
logger.log(Level.ERROR, message, e);
throw new YourException(message, e);
}
}
}
Hope this helps!
A few thoughts:
I presume from the title you were using e.printStackTrace(). This does not "clear the exception", so I'm not sure exactly what your issue really is on that point. In java "clear the exception" doesn't make any sense at all in this context.
e.printStackTrace() is "not a good idea" because it writes to standard out. Much better to write such detail to a log file for later diagnostics, rather than put it out in front of a user (though that could depend on how the program actually runs). Your run-time environment may have something to say about use of standard output.
e.getCause() will return, if available, an "underlying exception" that may have been a "root cause" for the exception e. Must stack traces will show this after an initial stack dump denoted by "Caused by: : ..."
If you choose to try to capture and display/log an exception yourself - you might use e.printStackTrace(PrintStream s) or e.printStackTrace(PrintWriter s).
You'd be best served using a logging tool, as suggested by Matt.

Which line in a long Java 'try' block is throwing an exception?

Is there a way to find out which line in a try block is throwing an exception?
I'm working on Java in Eclipse which looks like
try {
//Lots of code. Seriously. Lots.
} catch (Exception e){
throw new OtherException();
}
I'm hitting an exception in the try block, (which is then caught). How do I figure out where it's being thrown from?
Problems
The stack trace only shows the line in the catch block for the OtherException
Removing the try/catch block isn't straightforward, as there are many exceptions declared as thrown which are required to be caught in order for the code to compile.
It feels like there should be a straightforward way of doing this.
Note: I didn't write this code ;-)
Use the cause parameter for Exceptions (see here):
try {
//Lots of code. Seriously. Lots.
} catch (Exception e){
throw new OtherException(e); // Trick is here
}
This way you get the cause exception as well in the stacktrace.
You can use throw new OtherException(e);. As the documentation explains, this constructor constructs a new exception with the specified cause.
In Eclipse, you can set a breakpoint triggered by an exception. See Add Java Exception Breakpoint.
For this particular case, you'll need to ensure that "Suspend on caught exceptions" is ticked.
Once Eclipse breaks into the debugger, you'll have a lot of tools at your disposal. You'll see the call stack, will be able to examine variables etc.
Just print stacktrace or run on debug mode
e.printStackTrace()
Pass the exception e in your OtherException constructor when throwing it. It will give you the complete stack trace with the exact line throwing the exception:
catch (Exception e) {
throw new OtherException(e);
}
If OtherException doesn't have a constructor that takes an Exception or Throwable you could do:
catch (Exception e) {
OtherException o = new OtherException();
o.initCause(e);
throw o;
}
You can also try printing out the error message to the console: System.out.println(e.getMessage());
Breakpoints are very useful though, since you can then trace through the code and see exactly when it gets to the catch block.

Why does Throwable.getMessage() occasionally return null?

I have a method that sometimes throws an exception:
this.items[index] = element;
And I have a unit test that asserts that the exception that ought to be thrown is actually thrown:
try
{
doSomethingWithIndex(-1);
Assert.fail("should cause exception");
}
catch (IndexOutOfBoundsException expected)
{
Assert.assertNotNull(expected.getMessage());
}
This test runs as part of the continuous build and sometimes, occasionally it fails because getMessage() in fact returns null. Why would this happen? My code can never throw an exception with a null message.
EDIT
My original code example was misleading, the thrown exception is actually coming from directly indexing an array. I can reproduce the same behavior with a custom thrown exception though.
I added the suggested code:
catch (IndexOutOfBoundsException expected)
{
if (expected.getMessage() == null)
{
expected.printStackTrace();
}
Assert.assertNotNull(expected.getMessage());
}
The console output is missing the stack trace in addition to the cause. Here's the full output:
java.lang.ArrayIndexOutOfBoundsException
Found the answer on a similar question.
The JIT compiler will optimize away stack traces in certain exceptions if they happen enough.
The JVM flag -XX:-OmitStackTraceInFastThrow prevents this behavior and seems to fix the flickering unit tests.
Try printing stack trace of exception when it has null message. It's possible that some other code throws it. Like you actually accessing past array length.
You wrote that:
"My code can never throw an exception with a null message"
Are you yousing any 3rd party library? I assume standard java codes never throw exceptions like this above, but some pourly coded jar... :)

How to keep sysout and syserr streams from intermixing?

In my code base is the (very simplified) following:
public static void main (String[] args) {
System.out.println("Starting application");
try {
System.out.println("About to validate");
validate(args);
catch (Exception e) {
e.printStackTrace();
}
}
public static void validate(String[] args) {
System.out.println("Your first arg is " + args[0]);
if (someProblemWith(args)) {
System.out.println("Your args are wrong. It should be: ...");
throw new BadArgsException(e);
}
}
Which works fine. Note that my example code above is contrived and simply meant to show multiple log statements prior to exception and stack trace printing. This often means that my last logging statement is lost in the middle of the stack trace output. Is there an elegant way to ask the e.printStackTrace() statement to wait until the System.out has finished its work? I'm essentially looking for the stacktrace to be the very last thing printed when an error occurs. Here's a sample output of my program above:
java.lang.Throwable
....
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
Your args are wrong. It should be: ...
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56)
The reason you are seeing the stack trace being printed between the System.out.println() statements, is because System.out is buffered, while System.err (used by stack trace) is unbuffered.
If you want the text to be displayed in the exact order in which things are happening, you need to "unbuffer" the System.out. The simplest way is to also just use System.err there instead of System.out.
Otherwise, call System.out.flush() before your stack traces happen in the catch clauses.
Option 2: Use the Logger class.
Option 3: Implement your own "buffer". In other words, first write everything to your own buffer, including the stack traces (using .toString() or however you wish) and then in the catch flushing you own buffer. (This is kind of redundant since you can just flush the System.out anyway).
-==-
FROM COMMENT
Sure. The Logger class can be used to create a much more robust and detailed logging experience. This is typically what is done in applications. An instance of the Logger class is grabbed from the Logger class (it is a singleton), taking as parameter the class from which is will be used. Then you log messages to it by using the .log() method. The nice thing about the Logger class is that you can set levels on it (example DEBUG, WARN...) and you are then able to filter / display only what you want. The "log" messages are then displayed in a uniform way in the console, typically in the format of:
2010-11-23 14:45:32,032 DEBUG [MyClass] Your message
The above format is from log4j, but you can use the standard Java Logger. The output should be similar, maybe a bit less. But I'm sure it can be configured.
Call e.printStackTrace(System.out);. Or, if you need it for debugging only, you can separate the process' output and error from the command line: .... 1>output.log 2>error.log

Categories

Resources