Java: How to log where my function was called from - java

Is there a better way than wantonly throwing an exception and capturing the stacktrace to find out why (or at least from where) my function was called?
I can log the parameters the caller is using, but I cannot get the caller location itself. It is some third party software, so finding all references and adding log information there is not an option. I also hesitate attaching a debugger to a running jvm.

You can call Thread.currentThread().getStackTrace().
This will give you an StackTrace array the same way you would get if you'd thrown an Exception.
Hope this helps. :)

It's perfectly possible to create an exception, not throw it, and inspect its stacktrace:
Exception e = new Exception();
e.printStackTrace(System.out);
Note that doing it often may have a detrimental effect on the performance of your JVM.
StackTraceElement[] stacktrace = e.getStackTrace();
The 0th element of the stacktrace array will contain the method in which the exception was instantiated.

Related

Java exception design : must be caught or declared to be thrown => Too much code impact

Disclaimer : I'm coming from C# world so this is question might be biased by my previous experience
I have a method that is initializing logging. If this fails, the rest of the app should not run as any call to logger will throw a NullPointerException.
Today, my code is catching the exception and printing an error log via System.err. To me, this is a mistake, it should let the exception propagate up until it kills the app.
So I started removing the try catch and I suddenly got complains from the compiler saying that I should declare my exception on the whole stack where this method is called.
I understand the logic behind it and used to found it practical : you know how this method is capable of failing.
However, that doesn't sound right to me in term of separation of responsibility. I don't want the upper layers to be aware of this potential IOException fail, it is a very specialized behavior that shouldn't be known to , for example, the main method.
And, if we push this logic, it means that :
the highest layer will eventually have to declare the whole scope of exceptions (From IO to Network to custom exceptions...)
Any addition of a new exception can potentially impact a lot of files and code
Am I missing something or this is intended exception design ?
I think what you are looking for is not a Java Exception, it is a Java Error.
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.
https://docs.oracle.com/javase/7/docs/api/java/lang/Error.html
You can throw a error, which indicates that your app won't work anymore, which you declared as correct behaviour.
You can encapsulate your checked exception in a RuntimeException (or one if its children), which does not force you to declare the exception:
public X execute() {
try {
return someThrowingMethod();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
If you can't initialize the logger and this is an enterprise application, I recommend killing your application with an exit code that explains the reason. If this is a client application, I recommend showing a message to the client stating the problem, recommending to the client that you report this back to you, and allowing them the choice of whether to proceed or not

Throw exception vs Logging

Is the following way to code good practice?
try {
//my code here
} catch (Exception e) {
logger.error("Some error ", e);
throw new MyCustomException("Some error ", e);
}
Moreover, should I..
use only the logger?
throw only the exception?
do both?
I understand that with throw I can catch the exception in another part of the callstack, but maybe additional logging has some hidden benefits and is useful as well.
Normally, I'd argue that you should either log or rethrow. Doing both will just cause every layer to log the exception again and again, which makes the logs hard to read. Even worse, it's hard to figure out how many errors you actually have - was it seven errors, or seven layers of the app which logged the same error?
This means that if you suppress an exception, you log it and say why you didn't think it was worth rethrowing.
On the other hand, if you re-throw the exception, you know it's either going to be caught and suppressed (in which case the catcher logs the exception and why it was suppressed), or it will bubble up out of your app and be caught by the app container, which will catch and log the exception. Every exception shows up once and only once in the logs.
I use both in some cases, logging and throwing the exception. Especially, it's useful in APIs. By throwing the exception, we allow the caller to handle it, and by logging, we can identify the root cause of it ourselves.
And, if the caller is in the same system, then if we add logs in every catch, there will be duplicate logs.
When using the pattern you suggest, you usually end up with error events being reported multiple times in the log. In addition, it's not always simple to connect between them when reading the log.
Personally I prefer logging error events only once, and doing it in the higher call levels. Therefore I almost never log & re-throw. I usually let the exception go up the call stack until it reached a context where it can be handled somehow, and this is where I log.
If the exceptions are wrapped and re-thrown correctly, the context should be perfectly clear from the stack traces of the single log message.
The proper answer would be: "it depends"
You do want in general log the exceptions that you catch, since they correspond to something going wrong. That is why code analysis tools such as sonar will raise warnings when you do not log them.
Consider the following taks: parsing a file. While parsing the file you actually try to parse each line. Sometimes some lines will be malformed, and therefore you don't want to stop parsing the file because of it. In that case, you probably want to just log the wrong line and keep going on the file.
However, imagine that at some point you encounter an I/O exception while reading (for example some other program deleted the file while yours was accessing it).
In this case, you will probably want to log your log the error you encounter, and throw a new exception to stop processing the whole file.
So in short, you have to think about what is the best thing to do. But both practices are not bad.
I think you may need to use the pattern judiciously. As you've written the above, for each exception you're going to log 2 stacktraces and that may fill your logs with excessive information.
With respect to logging vs. throwing, they're two separate concerns. Throwing an exception will interrupt your execution, prevent any further work, perhaps rollback database commits etc. Logging will simply dump info to the log file (or elsewhere). It's of more use for debugging, and often much more difficult to test.
I know that is really old question, but I have an another solution.
Consider this. You can log the problem in catch block and throw a new unchecked exception (of course with passing the previous one inside). In such solution there is no overflow in the logs and exception still bubble up to the highest level.
try {
//my code here
} catch (SomeException e) {
logger.error("Some error occured", e);
throw new MyUncheckedException("Some error ", e);
}
My opinion.
When you need to throw an exception, no matter if it is a Checked or UnChecked(Most RD would not catch this.). It means that you want to do something else by stopping the process.
When you need to log something.
It means you want to track it.
It's quite different things.
You need to check what you really need.
BTW: If your exception was thrown by getting no data from DB.
I suggest you to modify the process to return an empty Data Object(POJO). It is better than throwing an exception.

InvocationTargetException caused by ArrayIndexOutofBound exception

i have a function where am using methodaccesor's invoke function,the problem is the application which am using is very vast,so there are times when this exception InvocationTargetException is thrown and the cause for this happens to be ArrayIndexOutofBounds Exception. The problem which occurs is comparitively less 8% of the transactions result in this (am unable to replicate this scenario),am unable to figure out what/how is causing this
can you guys please give me suggestions regarding this problem ,as to how to go about it?
am using reflector's PropertyUtils class here getindexedproperty is causing InvocationTargetException the thing am unable to replicate the issue what could be causing this as it happens very rarely
You are probably suffering from code that catches exceptions and does not log a proper stack trace.
Change all such instances in your code to do this instead:
try {
// dangerous stuff here
} catch (SomeException e) {
// Personally, I like to send a stack trace to stderr.
// You may prefer to print this to your log, eg if you don't capture stderr,
// or won't/can't for whatever reason.
e.printStackTrace(System.err);
}
And you will never again be at a loss as to where in your code these exceptions bubbled up from.
As you visit each try-catch, ask yourself if you should really be robust to such failures; sometimes the best thing is to let the code fail fast and not catch the exception in the first place. When the application fails due to some code/data that was in an incorrect state, you will find out quickly and get a roadmap (stack trace) to the root cause.

Custom exception. Where to log it

I created a CustomExceptionClass that its messages are from a configuration file and are a friendlier message to the user.
Then I want to log wich exception was thrown because, if something went wrong, I want to know details then I can fix this. So, I have a doubt.
Where to log these exceptions using log4j? Inside the CustomExceptionClass, or I let the method that throws this exception log it?
You should log wherever you are catching the Exception. If you are not catching it anywhere it really depends how you are running your application.
I'm not sure if you have a question about log4j in particular, but that API simply requires something to call log.error(Object,Throwable), passing in the message as the first parameter and the error as the second parameter. (log is of course a Log4J logger reference.)
Regarding the question of where to call log.error, do not call log.error from within your CustomExceptionClass subclass of Throwable. Instead, I'd make the decision as follows:
If you want to log details about exactly what happened, but you don't plan to put those details into your subclass of Exception, then log the details before throwing the error.
Similarly, if you want to log something specific regardless of whether or how the Exception is caught, then obviously you need to do this before throwing the Exception. You have relatively little control over who calls a non-private method.
Otherwise log in the catch block. This allows you to track both what happened and how your application responded as a result. If you just have the first piece of information, then other people will have to read the code in order to understand "so what?"
Finally, it's considered to be good practice to use uncaught exception handlers for all threads. See Thread.UncaughtExceptionHandler for more details. Basically you really want to at least log all Exceptions in long-running applications.
You should log it in the error handling code, not where the error is initially created.
I typically overload ToString and/or GetMessage in custom exceptions and simply log them per normal.

IllegalMonitorStateException

When running our program we get an exception of type java.lang.IllegalMonitorStateException. On Java6 API website, it says there is a constructor that gives a details about the exception: IllegalMonitorStateException(String s)
How can we use this to get a better idea of where the bug is in our code? Is there anything else we can do (besides lots of debugging which we're currently doing) to pinpoint the function or line that failed?
The details must be given when the Exception is created (Constructor, right?) and if you are not creating it, there is no way for you to provide the details.
You can analize the StackTrace of the Exception. It shows the classes, methods and souce line which were called to cause the Exception.
One cause for the IllegalMonitorStateException is trying to wait on an Object without having synchronized on it. See the Javadoc.
There are other possible causes and the Exception may be thrown by some library/external code. I think only the StackTrace can help...
This is maybe occurring because the instance of the object which you are calling wait or notify on is different that the instance you synchronized with. For example:
Integer a;
a = new Integer(0);
synchronized(a) {
System.out.printf("I synchronized on %h.", a);
++a;
System.out.printf("But, I am calling notify for %h and I hold no lock for it.", a);
a.notify();
}
This will throw the IllegalMonitorStateException because the instance that 'a' points to is no longer the same.
How can we use this to get a better
idea of where the bug is in our code?
Is there anything else we can do
(besides lots of debugging which we're
currently doing) to pinpoint the
function or line that failed?
In this case, printing the message by itself probably won't help much. What you need is a stacktrace with source file names and line numbers.
Make sure that all relevant ".class" files / JARs were built with file and line number debug information included. This is the default, but compiling with "-g:none" will strip this ... as will most JAR file obfuscators.
Next, add a try / catch block to catch the IllegalMonitorStateException and either call ex.printStackTrace() or log the exception.
From the stacktrace you should be able to see what line in the code threw the exception. The chances are that is was a call to Object.wait(...) or something like that. Check the javadoc for the offending method to find out what circumstances cause the exception to be thrown.
(And once you are done, remember to move the try / catch block you added.)
You should print the stack trace, which will give you the exact location in the source.
Unfortunately it's not uncommon for the JVM to throw exceptions which contain no detail message to assist in debugging.

Categories

Resources