I am writing a game program, and rarely i will get an exception. I want to be able to record all the exceptions i get on a separate thread. My program is already multi-threaded. In some cases i use try catch, and for those i could just set an exception variable to the caught exception. However i want to be able to find out all exceptions that have been thrown on all threads without putting every statement in a try catch. For clarification i want the exception object not just the name of the exception.
You want the Thread.UncaughtExceptionHandler:
Interface for handlers invoked when a Thread abruptly terminates due to an uncaught exception.
When a thread is about to terminate due to an uncaught exception the Java Virtual Machine will query the thread for its UncaughtExceptionHandler using Thread.getUncaughtExceptionHandler() and will invoke the handler's uncaughtException method, passing the thread and the exception as arguments. If a thread has not had its UncaughtExceptionHandler explicitly set, then its ThreadGroup object acts as its UncaughtExceptionHandler. If the ThreadGroup object has no special requirements for dealing with the exception, it can forward the invocation to the default uncaught exception handler.
See here for details.
This can be done using Spring AOP which is useful in these cases.
#AfterThrowing aspect
You will require Spring AOP libraries for that.
A similar question was answered previously.
This can be done through Java Debug Interface (JDI) that is part of Java Platform Debugger Architecture (JPDA).
In particular, see ExceptionRequest and ExceptionEvent.
Related
What happens if one throws a Java exception using ThrowNew from a natively-created thread?
If the native code that throws a Java exception is called from Java, then the exception goes back to the Java side as expected, but what if someone calls this native code without directly or indirectly coming from the Java? It's not going to go back to the Java obviously, since we're not coming from there.
Note: This answer is outdated as of Java 9 (which was not available when the answer was written).
If native code is making Java calls, it must have called AttachCurrentThread() to obtain a JNI env value if the native code is called in a manner that it did not have a JNI env passed to it.
So, before the native thread or call ends, it must call DetachCurrentThread(). But if there are any pending Java exceptions, DetachCurrentThread() will invoke the Thread.UncaughtExceptionHandler, as posted by #EJP.
Per the JNI specification regarding exceptions:
Exception Handling
There are two ways to handle an exception in native code:
The native method can choose to return immediately, causing the exception to be thrown in the Java code that initiated the native
method call.
The native code can clear the exception by calling ExceptionClear(), and then execute its own exception-handling code.
After an exception has been raised, the native code must first clear
the exception before making other JNI calls. When there is a pending
exception, the JNI functions that are safe to call are:
ExceptionOccurred()
ExceptionDescribe()
ExceptionClear()
ExceptionCheck()
ReleaseStringChars()
ReleaseStringUTFChars()
ReleaseStringCritical()
Release<Type>ArrayElements()
ReleasePrimitiveArrayCritical()
DeleteLocalRef()
DeleteGlobalRef()
DeleteWeakGlobalRef()
MonitorExit()
PushLocalFrame()
PopLocalFrame()
Note that DetachCurrentThread() is not safe to all with any pending Java exception.
Yet a native thread that has previously called AttachCurrentThread() must call DetachCurrentThread():
Attaching to the VM
The JNI interface pointer (JNIEnv) is valid only in the current
thread. Should another thread need to access the Java VM, it must
first call AttachCurrentThread() to attach itself to the VM and
obtain a JNI interface pointer. Once attached to the VM, a native
thread works just like an ordinary Java thread running inside a native
method. The native thread remains attached to the VM until it calls
DetachCurrentThread() to detach itself.
The attached thread should have enough stack space to perform a
reasonable amount of work. The allocation of stack space per thread is
operating system-specific. For example, using pthreads, the stack size
can be specified in the pthread_attr_t argument to pthread_create.
Detaching from the VM
A native thread attached to the VM must call DetachCurrentThread() to detach itself before exiting. A thread cannot detach itself if
there are Java methods on the call stack.
So native code must call DetachCurrentThread() before exiting, yet DetachCurrentThread() can not be safely called with Java exceptions pending.
In Java 8 and earlier, the only JNI functions that are safe to call with a pending exception are those which either release locks/references or themselves relate to exception handling. The idea is that when a JVM exception is passed to native code, it is supposed to either catch the exception itself or unwind the stack to a call frame that will. If a thread has no such call frame to unwind to, it follows that it should do the former. So the only specification-compliant way to handle an uncaught exception in a native thread was to clear it (i.e. call ExceptionClear) before calling DetachCurrentThread, perhaps after passing it to some custom handler.
In practice, if a pending exception made its way to the DetachCurrentThread call without being caught, the HotSpot VM has always handled them in the same manner as in JVM-managed threads, by passing it to the uncaught exception handler and terminating the thread. The problem is, the JNI specification did not offer a way for uncaught exceptions in native threads to defer to the JVM implementation’s uncaught exception handling in this manner.
This deficiency was noticed in two tickets: JDK-8155881 and JDK-8179050, but requiring HotSpot behaviour was deemed too burdensome for other implementations. As a compromise, in Java 9 the JNI specification was amended so that DetachCurrentThread is safe to call with a pending exception, but the effect of this is implementation-defined: ‘If an exception is pending when DetachCurrentThread is called, the VM may choose to report its existence.’. This wording remains there in JNI 15.
Long story short, if you just unwind the call stack while releasing all resources up to the point of DetachCurrentThread, you should probably be fine; with (a little) luck, the uncaught exception will be handled the same way as any other. But for extra safety, you should catch the exception yourself.
I asked a question about how to override the default Java Exception handling here and was told the answer here.
The question is now : is there a way to generify this handler to all threads without declaring explicitly in each thread ?
I think it should be possible to get all threads in some way, then bind them the exception handler ?
Use Thread.setDefaultUncaughtExceptionHandler. As the javadoc says:
"By setting the default uncaught exception handler, an application can change the way in which uncaught exceptions are handled (such as logging to a specific device, or file) for those threads that would already accept whatever "default" behavior the system provided."
Obviously, if a Thread already has a (non-default) handler, then it won't be affected by a change to the default behavior.
I think it should be possible to get all threads in some way, then bind them the exception handler ?
That's not necessary ... unless you want to change a thread's non-default handler. If you really need to do that, you can find all threads by traversing the application's ThreadGroup hierarchy. (Unless your app is sandboxed ...)
Edit
The thread list of the running app can be found using this answer :
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
You can use Thread.setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) for that case if i got it right.
See Thread.setDefaultUncaughtExceptionHandler
There is a method setDefaultUncaughtExceptionHandler in Thread
Given a thread that has finished doing some work (its status is Thread.State.TERMINATED), is there a way to understand if the thread has completed the Thread.run()/Runnable.run() method correctly or has thrown an uncaught throwable ?
Afaik, a thread goes into the TERMINATED state both when exiting normally and when throwing throwables.
Somebody suggested using an UncaughtExceptionHandler. Given that a thread can have only one UncaughtExceptionHandler (other than the default for all threads), and that the thread code can change the provided one, is it a good practice using them ?
Have you looked at Thread.setUncaughtExceptionHandler?
This lets you trap uncaufht exceptions if you have a handle on the thread?
You could install an UncaughtExceptionHandler or set the default UncaughtExceptionHandler and have it save the exception that the thread exited with.
The functionality you are interested in could be accomplished using a Callable that wraps it run method in a try { } catch block and returns the Exception within the Future object it it encountered a problem
I don't know if there is a way to directly do it, but you could surround all your code in the run method with a try/catch statement. If you create a boolean and set it to true when it terminates with a exception then you can you can check the state and if the boolean is true it terminated with an exception and if the boolean is false then it closed correctly.
There is probably a better way but this should work.
Is there a way to make my java application shut down there is an error? e.g. if I have a nullpointerexception, can I just make it completely close out?
Any uncaught exception at the top level will automatically halt the thread it's in. If you have more than one thread in your program, the other threads will still survive. If you want to terminate explicitly, you can call System.exit()
You can use System.exit(0); to terminate the JVM.
However, you should avoid NullPointerException by checking the reference before using it:
if(foo != null) foo.doSomething();
As others have said, catching the exception and calling System.exit() is (generally) the right approach. But there is more to it than that:
Q: Do I really need to catch it?
A: If your application is a conventional command-line application, and the exception is thrown on the "main" thread, then you may not need to catch it. Uncaught exceptions on the main thread will cause the application to exit ... if there are no other non-daemon threads in existence. (In fact, the same thing goes for any thread ... )
However if your thread has more than one non-daemon thread, then you need to do something to stop the application. Like catch the exception and call exit().
Q: Where do you catch it?
A: On the stack of any thread where the "fatal" exception might be thrown. There are two ways to do this:
Put a try / catch (Throwable) in the main(String[]) method, a thread's run() method, etcetera.
Install a default uncaught exception handler.
What you DON'T want to do is to add System.exit() calls all through your codebase. That approach leads to all sorts of problems with reusability, unit testing and generally figuring out "why has the effing application died again".
Q: What if it is already caught?
A: One reason why your application might not be exiting naturally, is that your code is already catching the exception ... by accident. For instance:
try {
doSomething()
} catch (Exception ex) {
handle an IO exception
}
In the above, some ignorant / lazy programmer hasn't bothered to consider the exceptions that might be thrown in doSomething and has assumed that they are all some kind of IO related exception. But if the exception was actually an unexpected NullPointerException ... or something worse ... then the code has just squashed it.
The cure for this kind of thing is code-reviews and mentoring to cure the programmer of his bad habits ... hopefully before he does too much damage to the codebase! And if you find this kind of thing in your codebase, you should fix it immediately ... and probably "grep" for similar occurrences and fix them too.
I am asking because if it is not, it can be abused as synchronizations mechanism. I am asking about Java.
I'm not sure what you mean by "can be abused as synchronizations mechanism" - that doesn't make sense.
Exceptions are per thread - when an exception is thrown, the current thread's execution jumps to the place where the exception is caught. If it's not caught at all, the thread dies. Other threads are not affected.
JLS 11.3.2 Handling Asynchronous Exceptions
Most exceptions occur synchronously as a result of an action by the thread in which they occur, and at a point in the program that is specified to possibly result in such an exception. An asynchronous exception is, by contrast, an exception that can potentially occur at any point in the execution of a program.
Proper understanding of the semantics of asynchronous exceptions is necessary if high-quality machine code is to be generated.
Asynchronous exceptions are rare. They occur only as a result of:
An invocation of the stop methods of class Thread or ThreadGroup
An internal error in the Java virtual machine
So no, while rare, not all Exception handling is synchronous.
No, it's synchronous.
Try stepping through your code with a debugger, you'll see that it executes line after line, and will not continue if you break inside the catch.
Exceptions occur during the execution of a thread. It does not make sense to have an asynchronous catch because the thread has to handle the exception. It cannot proceed till the exception is caught and taken care of. If the exception is not caught or thrown, the thread does not know what it has to do and simple dies and the program may/may not misbehave.
A thread throwing an exception and then proceeding without waiting for the catch does not make sense.
To answer your question, no catching is not asynchronous for all practical purposes.