How to identify a throwable with specific data - java

I have this caught that catches any uncaught exception
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
}
});
Inside the method, I want to deal with following exception differently than other exceptions:
Caused by: java.lang.NullPointerException
at com.company.si.stats.Statistics.hashString(Statistics.java:192)
at com.company.si.stats.Statistics.sendStatistics(Statistics.java:127)
I want basically to check that it is nullpointer exception coming from com.company.si.stats.Statistics.hashString
How can I do that? I am not sure what parameters in throwable I should compare against?
The code where exception is thrown was not written by me, so I cannot change anything about it.
Important NOTE
I know the way I am approaching this problem is not the right way. But I dont have access to the library raising the exception and I needed a workaround till the bug is fixed in the library. The answer was chosen because it satisfies what I need to, and not what generally should be dne

Disclaimer
This was suggested in the comments and I thought it will be a good idea to add it as an answer, but remember that this is not how you should do it, so please use this answer as an example of how NOT to handle this type of problem. Feel free to also downvote it.
You can check where the exception comes from by looking at its stack trace, or at least at first stack trace element.
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
StackTraceElement[] stackTrace = e.getStackTrace();
if (e instanceof NullPointerException &&
stackTrace != null && stackTrace.length >= 0 &&
"Statistics.java".equals(stackTrace[0].getFileName()) &&
"hashString".equals(stackTrace[0].getMethodName()) &&
192 == stackTrace[0].getLineNumber()) {
// Handle your exception here.
}
}
});
Reasons why you should not do it:
it's really ugly
any change in hashString method will make this useless
because mom said so
any change in Statistics class will make this useless
in case of 2 or 4, finding bugs caused by this exception could be really painful
it's not portable (think about changing the library in the future)
it's bad practice

You can create your own exception, for instance:
public class HashingException extends RuntimeException {
public HashingException(Throwable t) {
super(t);
}
}
As you said, the com.company.si.stats.Statistics.hashString() method wasn't made by you so you can't change it. But you can translate the exception thrown by it. I'm not sure how the method signature looks like, but here's how you can do it:
// ... some code, Statistics object initialization somewhere
String hashString;
try {
hashString = statistics.hashString(someArgumentMaybe);
} catch (Exception e) {
throw new HashingException(e);
}
// result of method is available here as hashString object
and later handle it in your handler class like:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
if (e instanceof HashingException) {
HashingException hashingException = (HashingException) e;
// Handle your exception here.
Exception cause = e.getCause();
// cause will be NullPointerException
}
}
});

There is a simple way to get your stacktrace as a String or a reader
ByteArrayOutputStream stacktraceContent = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(stacktraceContent));
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(new
ByteArrayInputStream(stacktraceContent.toByteArray())))) {
// Here you can read your stacktrace line by line and match against any
// pattern
}
Also there is a nice Open Source library that filters logs. Its called MgntUtils library. Here you can find an article describing it in detail:
Open Source Java library with stack trace filtering, Silent String parsing Unicode converter and Version comparison. The article also provides links to github (source) and Maven where you can download it or integrate it into your Maven project. Here are the links anyway: MgntUtils on github and Maven link

Related

How to make sure that exceptions do not lose its stack trace information in java?

Recently, I met some exception problem in java, which reminded me of the typical idiom recommended by Bruce Eckel:
Converting checked to unchecked exceptions
The real problem is when you are writing an ordinary method body, and you call another method and realize, "I have no idea what to do with this exception here, but I don’t want to swallow it or print some banal message." With chained exceptions, a new and simple solution prevents itself. You simply "wrap" a checked exception inside a RuntimeException by passing it to the RuntimeException constructor, like this:
try {
// ... to do something useful
} catch (IDontKnowWhatToDoWithThisCheckedException e) {
throw new RuntimeException(e);
}
This seems to be an ideal solution if you want to "turn off the checked exception—you don’t swallow it, and you don’t have to put it in your method’s exception specification, but because of exception chaining you don’t lose any information from the original exception.
This technique provides the option to ignore the exception and let it bubble up the call stack without being required to write try-catch clauses and/or exception specifications.
However, I found it didn't work in some cases. as seen here:
package exceptions;
// How an exception can be lost
class VeryImportantException extends Exception {
#Override
public String toString() {
return "A very important exception";
}
}
class HoHumException extends Exception {
#Override
public String toString() {
return "A trivial exception";
}
}
public class LostMessage {
void f() throws VeryImportantException {
throw new VeryImportantException();
}
void dispose() throws HoHumException {
throw new HoHumException();
}
public static void main(String[] args) {
try {
LostMessage lm = new LostMessage();
try {
lm.f();
} catch (VeryImportantException e) {
throw new RuntimeException(e);
} finally {
lm.dispose();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}/* Output:
Exception in thread "main" java.lang.RuntimeException: A trivial exception
at exceptions.LostMessage.main(LostMessage.java:36)
Caused by: A trivial exception
at exceptions.LostMessage.dispose(LostMessage.java:23)
at exceptions.LostMessage.main(LostMessage.java:33)
*///:~
As the output demonstrated, the second exception completely obliterates the first one. There is no record of the first exception in the exception stack trace, which can greatly complicate debugging in real systems. usually, it’s the first exception that you want to see in order to diagnose the problem.
Joshua Bloch recommends the try-with-resource way that a resource must implement the AutoCloseable interface, which process is somewhat complex.
So, my question is this: is there any way I can use to make sure that exception will not lose its stack trace information by Bruce Eckel's approach?
You might want to consider using try-with-resource instead of a finally block. It tends to handle this situation more like it sounds you would want the situation handled. See this article for more details.
Alternatively, you could simply eat the exception (as Andy Thomas's answer shows), or (if you want to know about both exceptions that were thrown) you could combine the exceptions into a single kind of Aggregate Exception.
The problem isn't that you're wrapping the exception. The problem is that you're replacing it with a subsequent, unrelated exception thrown from the finally block.
One easy way to avoid this is to not throw an exception from the finally block.
For example:
try {
LostMessage lm = new LostMessage();
try {
lm.f();
} catch (VeryImportantException e) {
throw new RuntimeException(e);
} finally {
try {
lm.dispose();
} catch ( HoHumException e ) {
// No-op or logging
//
// If we're exiting this try-finally because an exception
// was thrown, then don't allow this new exception to replace it.
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}

Retrieve contents of all stack traces being printed to the console?

I want to individually log every unique error I have, as searching though a dozen log files each +10k lines in length is time wasting and tedious.
I catch all exceptions I possibly can, but oftentimes other threads or libraries will shoot off their own errors without any way to process them myself.
Is there any workaround for this?
(E.G. an event for when printStackTrace() is called.)
Is there any workaround for this?
(E.G. an event for when printStackTrace() is called.)
Remap System.err to intercept throwables. If you look at the source code for Throwable.printStackTrace() you'll see that it indirectly calls System.err.println(this);
For example:
import java.io.PrintStream;
public class SpyPrintStream extends PrintStream {
public static void main(String[] args) {
System.setErr(new SpyPrintStream(System.err));
System.setOut(new SpyPrintStream(System.out));
new Exception().printStackTrace();
}
public SpyPrintStream(PrintStream src) {
super(src);
}
#Override
public void println(Object x) {
if (x instanceof Throwable) {
super.println("Our spies detected "+ x.getClass().getName());
}
super.println(x);
}
}
Keep in mind there is all kinds of issues with using this code and it is not going to work in cases where printStackTrace is called with stream that is not standard stream.
You could always do a deep dive into java.lang.instrument if you really want to trap all exceptions.
I catch all exceptions I possibly can, but oftentimes other threads or libraries will shoot off their own errors without any way to process them myself.
Most libraries either throw exceptions back to the caller or use a logging framework. Capture the exception or configure the logging framework.
I want to individually log every unique error I have, as searching though a dozen log files each +10k lines in length is time wasting and tedious.
Logging frameworks include options to deal with this. DuplicateMessageFilter is an example.
Food for thought:
public class DemoClass {
private Map<String, Exception> myExceptions = new HashMap<>();
public void demoMethod() {
try {
// throwing an exception for illustration
throw new IOException("some message");
} catch (IOException e) {
myExceptions.putIfAbsent(e.getLocalizedMessage(), e);
// actually handle the exception
...
}
}
public void finished() {
for (Exception e : myExceptions.values()) {
e.printStackTrace();
}
}
}
You could store any exception you haven't seen yet. If your specific scenario allows for a better way to ensure you only save an exception only once you should prefer that over mapping by Exception.getLocalizedMessage()

Rescuing a swallowed Exception in Java

Some 3rd party library swallowed an Exception:
String getAnswer(){
try{
// do stuff, modify instance state, maybe throw some exceptions
// ...
return computeAnswer();
}catch (SomeException e){
return null;
}
}
As much as I want to change it into:
String getAnswer() throws SomeException{
// do stuff, modify instance state, maybe throw some exceptions
// ...
return computeAnswer();
}
I can't, because the library is already packaged into a jar. So, is there a way to bring the exception back?
I don't need to rethrow, a stacktrace with exception and message would work too.
I don't think reflection would help here, Unsafe perhaps?
Yes I know I can use a debugger to find out what's happening, but that wouldn't be very useful if I need the exception at runtime for logging and stuff like that
You can do it without reflection or AOP. The main idea is to throw another (unchecked) exception in the constructor of SomeException. There are some limitations (see at the end of this answer) but I hope it fits your needs.
You need to replace the SomeException with a new version (just create a SomeException.java file in the original package but in your src directory) with something like :
package com.3rdpartylibrary;
public class SomeException extends Exception {
public static class SomeExceptionWrapperException extends RuntimeException {
public SomeExceptionWrapperException(final SomeException ex) {
super(ex.getMessage(), ex);
}
}
public SomeException(final String message) {
super(message);
throw new SomeExceptionWrapperException(this); //<=== the key is here
}
}
The SomeExceptionWrapperException has to be unchecked (inherit from RuntimeException or Error). It will be our wrapper to carry the SomeException accross the ugly 3rd party catch(...)
Then you can catch the SomeExceptionWrapperException in your code (and eventually rethrow the original SomeException:
//original, unmodifiable 3rdParty code, here as a example
public String getAnswer() {
try {
//some code
throw new SomeException("a message");
} catch (final SomeException e) {
return null;
}
}
//a wrapper to getAnswer to unwrapp the `SomeException`
public String getAnswerWrapped() throws SomeException {
try {
return getAnswer();
} catch (final SomeExceptionWrapperException e) {
throw (SomeException) e.getCause();
}
}
#Test(expected = SomeException.class)
public void testThrow() throws SomeException {
final String t = getAnswerWrapped();
}
The test will be green as the original SomeException, will be thrown.
Limitations:
This solution will not work if either :
if SomeException is in java.lang as you cannot replace java.lang classes (or see Replacing java class?)
if the 3rd party method has a catch(Throwable e) (which will be horrible and should motivate you to ignore the full 3rd party library)
To solve this based on your constraints I would use aspects (something like AspectJ) and attach it to the creation of your exception, logging (or having it call some arbitrary) method then.
http://www.ibm.com/developerworks/library/j-aspectj/
If all you're looking for is to log the stacktrace + exception message, you could do that at the point you're throwing your exception.
See Get current stack trace in Java to get the stack trace. You can simply use Throwable.getMessage() to get the message and write it out.
But if you need the actual Exception within your code, you could try and add the exception into a ThreadLocal.
To do this, you would need a class like this that can store the exception:
package threadLocalExample;
public class ExceptionKeeper
{
private static ThreadLocal<Exception> threadLocalKeeper = new ThreadLocal<Exception>();
public static Exception getException()
{
return threadLocalKeeper.get();
}
public static void setException(Exception e)
{
threadLocalKeeper.set(e);
}
public static void clearException()
{
threadLocalKeeper.set(null);
}
}
... then in your code which throws the Exception, the code that the 3rd party library calls, you can do something like this to record the exception before you throw it:
package threadLocalExample;
public class ExceptionThrower
{
public ExceptionThrower()
{
super();
}
public void doSomethingInYourCode() throws SomeException
{
boolean someBadThing = true;
if (someBadThing)
{
// this is bad, need to throw an exception!
SomeException e = new SomeException("Message Text");
// but first, store it in a ThreadLocal because that 3rd party
// library I use eats it
ExceptionKeeper.setException(e);
// Throw the exception anyway - hopefully the library will be fixed
throw e;
}
}
}
... then in your overall code, the one that calls the third party library, it can setup and use the ThreadLocal class like this:
package threadLocalExample;
import thirdpartylibrary.ExceptionEater;
public class MainPartOfTheProgram
{
public static void main(String[] args)
{
// call the 3rd party library function that eats exceptions
// but first, prepare the exception keeper - clear out any data it may have
// (may not need to, but good measure)
ExceptionKeeper.clearException();
try
{
// now call the exception eater. It will eat the exception, but the ExceptionKeeper
// will have it
ExceptionEater exEater = new ExceptionEater();
exEater.callSomeThirdPartyLibraryFunction();
// check the ExceptionKeeper for the exception
Exception ex = ExceptionKeeper.getException();
if (ex != null)
{
System.out.println("Aha! The library ate my exception, but I found it");
}
}
finally
{
// Wipe out any data in the ExceptionKeeper. ThreadLocals are real good
// ways of creating memory leaks, and you would want to start from scratch
// next time anyway.
ExceptionKeeper.clearException();
}
}
}
Beware of ThreadLocals. They have their use, but they are a great way of creating memory leaks. So if your application has a lot of threads that would execute this code, be sure to look at the memory footprint and make sure the ThreadLocals aren't taking up too much memory. Being sure to clear out the ThreadLocal's data when you know you no longer need it should prevent that.
JVMTI agent can help. See the related question.
I've made an agent that calls Throwable.printStackTrace() for every thrown exception, but you may easily change the callback to invoke any other Java method.
A rather dirty trick that could do the job with less effort than AOP or de-/recompile the JAR:
If you can copy the source code, you can create a patched version of the class in question with your version of the getAnswer method. Then put it on your classpath before the third party library that contains the unwanted version of getAnswer.
Problems could arise if SomeException is not a RuntimeException and other third party code calls getAnswer. In this situation I am not sure how the resulting behavior will be. But you could circumvent this by wrapping SomeException in a custom RuntimeException.
Could you not just use a reference variable to call that method, if the result is a null, then you can just display a message/call an exception, whatever you want?
if you're using maven, you would exclude packages of the library.
Dependency Exclusions.
I hope to be helpful
If you have the source to the throwing class, you can add it "in the original package but in your src directory" using the technique as #Benoît has pointed out. Then just change
return null;
to
return e;
or
e.printStackTrace();
etc.
This would be quicker then making a new Exception.

Java 1.5 compatible pattern that will handle all possible exceptions without exception swallowed/lost and resources closing?

I have some method that uses some resources that should be closed at the end and the method itself and resource closing could throw everything including IO Connection and so on exceptions, some Runtime exceptions and even Errors (everything what inherits Throwable OOM is often case.).I want to handle all Exceptions without losing information and to send/throw the most important exception to the client (supposingly the runtime exceptions/errors?) This is the pattern I use (it's java 1.5 so I can't use resource features from 1.7):
Throwable thr=null;
try {
methodThatCouldThrowCheckedExceptionAndErrorAndRuntimeExcpetion();
log("method succesfully executed.");
} catch (IKnowThisException ikte) {
//Exception will be not lost
log("Method was not executed ,and I can suggest further actions",itke);
thr=ikte;
} catch (Throwable t) {
// This exception will be not lost too
log("Method was not executed ,and I don't know why.",t);
thr=t;
} finally {
try{
// The method below - of course contains the standard null checkers.
closeResourcesMethodThatCouldThrowEverythingToo();
log("resources were closed.");
} catch (IKnowThisEscpetionToo iktet) {
log(iktet);
throw new IllegalStateException("Resources were not closed , because of the known exception and I can suggest some actions" , ijtet);
} catch (Throwable t) {
log(t);
throw new IllegalStateException("Resources were not closed and I don't know why" , t);
}
// in case resources are closed we can re-throw exception from try{} block
if ( thr != null ) {
throw thr;
}
}
But I'm not completely sure it's the best approach .Here a similar approach i sused . But it does not handle unchecked exceptions (do I need to handle them?) Is there a case when I can lost valuable information? In the most examples I found nothing special is done about Errors/RuntimeExcpetions , but I want them logged. Is there a better approach? May be I should construct a more complicated chained exception to keep information compacted?
To preserve all of the errors, it would be best to use a custom exception class, that provides something like ARM's "suppressed exception" collection.
If the method throws an exception, this is the (cause of the) main exception. If closing resources raises additional exceptions, they are added to the main as suppressed exceptions.
If the method completes without failure, but closing resources raises an exception, the first becomes the main exception, and subsequent resource close failures are added to it as suppressed exceptions.
If a resource was intended to have side effects like writing a file or updating a database, the application needs to determine what to do when closing that resource fails. Using a general purpose mechanism that hides those resource closure exceptions would not allow the application to make that determination, and would only be useful in the rare cases where the application doesn't care if any output is actually produced.
I would look at how the compiler rewrites the try-with-resources pattern in Java 1.7. Below is a simple example of the pattern in source level 1.7, followed by a decompiled version with try-with-resources sugaring disabled:
// Original:
public void test() throws IOException {
try (final StringWriter writer = new StringWriter()) {
writer.write("This is only a test.");
}
}
// Decompiled:
public void test() throws IOException {
final StringWriter writer = new StringWriter();
Throwable t = null;
try {
writer.write("This is only a test.");
}
catch (Throwable t2) {
t = t2;
throw t2;
}
finally {
if (writer != null) {
if (t != null) {
try {
writer.close();
}
catch (Throwable t2) {
t.addSuppressed(t2);
}
}
else {
writer.close();
}
}
}
}
Sadly, the addSuppressed() method was only introduced in Java 1.7, but you could create a custom exception class that introduces this behavior, as #erickson suggests in his answer. If only one exception occurs, simply rethrow that one. Otherwise, replace it with the custom exception, wrap the original as the cause, and add any suppressed exceptions that occurred during closing of resources.
As I know, un-checked exception should not be handle. But you can handle by catching broader exception such as "Exception" before finally block.
I suggest you read my blog post Clean Up After Yourself (Grab my Close class) and then
import static com.frischcode.util.Close.close;
// Where ... is any number of things to close (in finally block - naturally).
close(...);

Throwing a Linked List of Exceptions in Java

I have a function that loops while doing something that could throw an exception. Looks something like this:
public void myFunction() throws MyException {
while(stuff) {
try {
DoSomething() // throws an exception
}
catch (Exception ex) {
throw new MyException(some, stuff, of, mine, ex);
}
}
}
The error causing the exception is recoverable. It can be something like an SQL error in a single update statement where the while loop executes a series of update statements. Or a parsing error in a single piece of data, where the loop is processing multiple pieces of data. I need to pass the exception further up the chain so the GUI part of the program can process it, handle it and pass on the error to the user. But I don't want to kill the loop in this particular function. The other things it's doing might not be invalid. The error that caused the exception might not be fatal to the function.
So my question is this: Is it an acceptable practice to build linked lists of custom exceptions (where each exception is a node, and the exception thrown is the head of the list) and then throw the head of the list (if any) once the loop finishes?
Has anyone ever seen this done? Can anyone think of any potential problems with doing this? Can anyone think of other, better ways to handle the root problem: the need to pass up multiple unrelated exceptions with out exiting the function until it is done?
Here's an example of how the linking and throw might be implemented very simply:
public void myFunction() throws MyException {
MyException head = null;
while(stuff) {
try {
DoSomething() // throws an exception
}
catch (Exception ex) {
MyException tmp = new MyException(some, stuff, of, mine, ex);
tmp.next(head);
head = tmp;
}
}
if(head != null)
throw head;
}
My intial thought (other than I've not seen this) is that an exception is potentially quite a large object (containing the stacktrace) and I'd prefer not to store a lot of them.
I would instead build a list of the erroneous parameters/arguments as exceptions occur, and upon completion of the loop, throw a custom exception populated with this list (if the list has more than 0 elements). That would seem a more manageable way of handling this scenario.
public void myFunction() throws CustomException {
List<MyError> errors = new ArrayList<MyError>();
while(stuff) {
try {
DoSomething() // throws an exception
}
catch (Exception ex) {
errors.add(new MyError(some, stuff, of, mine, ex));
}
}
if (errors.size() > 0) {
throw new CustomException(errors);
}
}
Do you really need to throw all the exceptions? How do you expect to the individual, unrelated exceptions to be handled? Generally in cases like this, the system will just report the errors and be done with it.
If so, you might want to just collect the error messages and add them to a custom Exception class and throw that.
If those exceptions are really unrelated to each other so that you can't take benefit of get/setCause(), then I would rather collect this information in one MyException.
E.g.
public void myFunction() throws MyException {
MyException myException = null;
while(stuff) {
try {
DoSomething() // throws an exception
}
catch (Exception ex) {
if (myException == null) {
myException = new MyException();
}
myException.addException(some, stuff, of, mine, ex);
}
}
if (myException != null) {
throw myException;
}
}
Update: Brian handles exactly this approach in a more neat manner. I would opt for that instead :)
Actually throwing any exceptions from such a function is probably not the right way to handle this if it is expected that there will be errors. I'd suggest to either return a List (Array) of all exceptions/errors that occured or better to provide a error handler object to the function that can deal with the exceptions. i.e.:
public interface ErrorHandler
{
public void handleError( Throwable ex /*, add some context info */ );
}
public void myFunction( ErrorHandler eh )
{
while(stuff) {
try {
DoSomething() // throws an exception
}
catch (Exception ex) {
if( eh != null )
eh.handleError( ex );
}
}
}
This also lets the error handler either collect the errors to present them to the user or to decide that the whole batch operation has become void because of some error and to throw a exception of it's own to abort the processing early.
If the exception thrown by DoSomething(); could cause the very same method to throw another exception; this might be a problem. In other words, if DoSomething(); throws an exception because you didn't handle the previous one, there might be unnecesarry error to handle.
I think you can pass some callback or listener to the method, or set in a class variable and instead of a throw the list, like x4u did.
In Java there is an interface for this already: java.beans.ExceptionListener
IMO, an exception should be the last resource you have for handling an error. It should be avoided if possible. So, you might want to pass the error description (create error codes, pass the message, or something meaningful) to the GUI, and not the exception itself.

Categories