how can i find out which class/method has called the actual method?
You could try to create an exception to get its stacktrace.
Throwable t = new Throwable();
StackTraceElement[] stackTraceElements = t.getStackTrace();
Now stackTraceElement[0] contains the caller of the current method.
But beware (from Throwable.getStackTrace()):
Some virtual machines may, under some
circumstances, omit one or more stack
frames from the stack trace. In the
extreme case, a virtual machine that
has no stack trace information
concerning this throwable is permitted
to return a zero-length array from
this method. Generally speaking, the
array returned by this method will
contain one element for every frame
that would be printed by
printStackTrace.
Here's one way that I've used:
StackTraceElement element=Thread.currentThread().getStackTrace()[3];
String className=element.getClassName();
String methodName=element.getMethodName();
[3] is hardcoded because:
[0] is Thread.dumpThreads()
[1] is Thread.getStackTrace()
[2] is the current method
[3] is the one before the current method
A faster but non-portable solution is to use the following. It does not create a stack trace and just gives you the information you need. However, not all JVMs will have this and future version of Java might not either.
Class callerClass = sun.reflect.Reflection.getCallerClass(2);
You can print a stack trace to do this.
If you want to do this dynamically, I'm not really sure if this is possible (aside from printing and parsing a stack trace dynamically).
You could use a debugger, or a profiler. Netbeans has both, but a lot of other options exists.
Else, if you can modify the code you can throw a new exception() and have a stacktrace printed in the console.
To echo and elaborate on matt b and yishai's comments:
If you are doing this because you are writing a logger or maintaining trace information or some such, okay, cool. I've used stack traces in production code exactly once, and even that was really a debugging issue: We had a problem with database connections not being properly closed, so I modified the "get database connection" function to save the identity of the caller, and then had a periodic sweep to look for dead connections and see where they had been created.
Java's built-in logging function does stack traces so it can write who called the logger to the log file. I worry about the overhead of this as I understand that stack traces are expensive, but whatever.
But if you're doing this because your function is going to behave differently depending on where it was called from, like "if called from class X update customer data else if called from class Y update employee data" or something like that: Really really bad idea. Pass a parameter or write separate functions.
Related
I have made a nice UI with three different logs (a general log and two class specific ones).
Every log can print different lines with different colors.
I was thinking of doing this so I can show info/errors/warnings.
Now, the thing is, that I'd like to have detailed debug only when I set a variable (something like detailedDebug = true).
I'd like something like this:
Simple | Detailed
Error thrown in ... | Error thrown.. + dump of all variables related to the error
Now, with if statements I can achieve that easily, but, that seems overly complicated (complicating the code for debugging reasons too).
How could I implement this (while making it easy to use and most importantly clean)?
Should I make a method in every class that uses the logging features that automatically checks for a variable then does what asked?
You should use the the log level as the variable to control the detail. When you want more detail, turn the level down to FINEST.
Hoewever, some operations that you wish to log might require considerable resources to calculate the detail (example, you may retrieve info from the DB, etc). In this case you should use if statements because the resources will be consumed even if the log level is at ERROR level.
Example :
The following code will always execute :
logger.log(Level.FINEST, "Some detailed log info which sows the results from DB {0}",
new Object[]{ getResults() });
If you only want to execute this code when you are showing FINEST, you need to wrap the statement in an if statement :
if (logger.isLoggable(Level.FINEST)) {
// Some intensive logging
}
I have been tasked with logging the line number as part of the error code shown to the user. Currently I am using:
StackTraceElement[] stackTraceElement = e.getStackTrace();
lineNumber = stackTraceElement[0].getLineNumber();
I know that the above approach may fail depending on the JVM version.
Also, I have seen the PatternLayout where it is mentioned that "Generating caller location information is extremely slow. Its use should be avoided unless execution speed is not an issue.".
Since this message will be presented to the user, should I still log the line number as part of the error code? I am trying to understand the pros and cons of this approach. Also, does the log4j warning apply only to its own implementation or rather is it a warning against location information generally?
Well, generally speaking your program should report two kind of errors:
The errors that are for the user (when the user is not doing what is expected from him), which should actually be better called "feedback" to help him feed your program with the right data (that's good UX practice).
The errors that are generated because of a bug, which are actually not targeted at the user, but at you the developer, sadly through the user. Then yes, it might be a good idea to log line numbers (or give your errors unique names/identifiers so that you can trace easily where it's been sent from). But a better idea is to then use a framework to report such issues directly to you through Internet (good practice being to ask for permission first).
What you should show to the user is what went wrong and what he can do about it, if anything. The line number information needs to be available, e.g. via a 'More details' button, in case he needs to raise a support ticket, but you don't want to frighten him or confuse him with it up front. Just look at how many stack traces get misread or indeed ignored completely here, and this community is supposed to be computer programmers.
Generally its better if your program doesn't give errors, and can receive all input, and give you tips on how to use the application. This will give users a much better experience if you want them to buy your product, etc.. If your program does give errors, it will not be helpful for the user to know the line number. You however will want to know the line number, so you should make it display a message of some sort that tells the user to email you the stack trace when the error occurs. Or you could have it report the error message automatically and email it to you.
Sorry, I'm a bit late I was unclear what the question was asking, so I posted this as a comment, but clearly it is an acceptable answer.
I'm developing a plug-in for the Eclipse platform. This plug-in will be used to give information about the line of Java source code currently being debugged.
When debugging a Java program, as you hit a breakpoint, Eclipse switches to the standard Debug perspective. Inside this perspective, apart from the standard Console output, the stack trace and various other views, you can see source code of the Java program currently being debugged. Inside this 'source code view', you can see a highlighted line, which is the line of code currently being debugged/evaluated. This highlighted line of code is what I want to access.
Assuming I know when the debugger is running (I assess that through a DebugBreakpointListener class that implements IJavaBreakpointListener), I need to 'ask questions' to the debugger. What, I imagine, I will need, is to somehow ask the debugger directly either for the line of code it is currently highlighting/debugging/evaluating or for the line number of the said line of code.
I'm making a static access to the JDIDebugModel to add the Java Breakpoint Listener:
JDIDebugModel.addJavaBreakpointListener(new DebugBreakpointListener);
I thought I could access the debugger with static references to JDIDebugPlugin but I've yet to find what I'm looking for.
At Part 3 of this research paper, the authors suggested that:
The Eclipse Java debugger is built upon the API of Java Debug Interface (JDI), which is part of the Java Development Toolkit. This API enables adding requests to monitor JVM events such as BreakpointEvent. When an event occurs, the debugger gets a notification and the thread in which this event took place can be obtained. For each frame in the stack trace of this thread the following information can be obtained:
• The source Java file in which the execution at this frame has taken place (or null if the source is not available).
• The method and line number (if available).
• The this object or null if the method is static.
The Eclipse debugger uses this information when a breakpoint is hit. It shows the stack trace for the suspended thread in the ”Debug” view. For the selected frame in this trace, Eclipse highlights the corresponding line number in its source file, and displays the this variable in the ”Variables” view.
This bulletpoint-listed things are exactly what I'm looking for.
Unfortunately, I can't find detailed documentation on how to 'plug in' to the debugger.
If someone can give me information, point me to information or a sample code, or maybe provide me with contact information of someone from the Eclipse JDI project, it would be immensely appreciated.
Thanks in advance.
------Update & Answer:------
With the help of greg-449's answer, I did exactly what I wanted to do. Here's what I did:
The aformentioned breakpoint listener I wrote implements the interface method breakpointHit, which is as follows:
#Override
public int breakpointHit(IJavaThread thread, IJavaBreakpoint breakpoint) {
System.out.println("Just hit a breakpoint!");
// Save pointers to the thread & breakpoint for future use.
return 0;
}
With the pointers to the thread and breakpoint objects saved in one of my objects, I could query them to get up-to-date information on the state of the frame stack, the thread and about the particular breakpoint that I've hit. I can get the namea dn path of the class the debugger is currently debugging by calling:
IStackFrame topStackFrame = thread.getTopStackFrame();
int debuggedLineNumber = topStackFrame.getLineNumber();
String debuggedClassPath = topStackFrame.getLaunch().getSourceLocator().getSourceElement(thread.getTopStackFrame()).toString();
This was exactly what I was looking for. I imagine I will need to read the source code files manually, run them through a tokenizer by having the 'newline' character as a delimiter and get the corresponding token to read that specific line.
There is a huge amount of information available in the IJavaThread and IJavaBreakpoint arguments passed to the breakpointHit method of the IJavaBreakpointListener which should contain this information.
I think for breakpoints which have a line number (not all do) the IJavaBreakpoint argument also implements ILineBreakpoint containing the line information.
I am looking for a way to get a stack trace when I am at a certain breakpoint. Is this possible? Ideally without having to crash the application and modifying the code. I tried playing with the Android debugger but couldn't find anything very helpful.
The reason is that sometimes I am not certain how the application arrived at a point in code, so I am open to other suggestions that would help me trace the method calls.
This can be done in Java:
new Throwable().printStackTrace();
In Eclipse, if you create an "expression" with that code in the Expressions view of Debug perspective, it will print current stack trace (i.e. the stacktrace of the breakpoint your code stopped on) in the Console view.
Log.e("AppName", "Debug exception", new Exception());
The easiest way is to throw an exception, immediately catch it and use printStackTrace().
You could also try Thread.currentThread().getStackTrace() which gives you a StackTraceElement[] in case you want to to anything else besides having the textual representation that printStackTrace() does.
I use sl4j / logback as a logging framework. I am unsure about the right way to log errors. Namely, assuming e is an Exception I want to log, I always hesitate between:
logger.error("Something bad happened: {}\nError: {}", someInfo, e.getMessage());
I understand this is not good practice because the stack trace is lost - not great to understand what happened.
logger.error("Something bad happened: {}\nError: {}", someInfo, e.getMessage(), e);
Using both e.getMessage() and e seems redundant, although I don't know if it is possible that e.getMessage() might contain extra information that would not be seen if I used:
logger.error("Something bad happened: {}", someInfo, e);
which is the syntax I generally use - but I want to make sure I am not missing anything.
I usually use number two, although I NEVER break one line of log into 2 lines (\n), although when printing the stack trace, it won't matter much (in all other cases, it creates too much visual entropy when your logs become really huge).
Why do I use number 2?
I want to see the message right away, on the first line, since it's the first thing that tells me what happened. Some might be expected and I can safely skip them, and some might not be.
In case I need to examine exactly what happened, I take a better look at the stack trace.
I reckon number 3 is also fine, since you'll get the information you need anyway.
NEVER use option 1.
By the way, and just a particular opinion, saying that something bad happened on a ERROR line is a bit redundant ;)
If you look at the source code of Throwable (http://www.docjar.com/html/api/java/lang/Throwable.java.html) you'll find that a Throwable when asked to print its stacktrace starts by priting itself, which prints its message.
I find it unlikely that anybody would change this behaviour, so your arguments are all correct and the 3. option is fine
You definitely want the stack trace.
Message is handy in circumstances where you've done something like "Error : Unable to find customer with ID : {0}", which may not be in the stacktrace. Trivial example but you get what I mean.
Another one for message is if you do the log as say a csv so you can analyse it. You can standarise message, and make filtering easier.
Last but not least redundant info in an error log, is way way way less of a problem, then the info you need not being in it. Err on the side of extreme verbosity is my guiding principle.
Oh this is for contrrolled access to a log file ,never say put stack trace as a response in asp for instance. Hackers wet dream that.