Bug in uncaughtException ?
Wondering if there is a bug in how uncaughtException is called?
I've created a simple app (listed below) that illustrates the problem.
When I'm pressing the button on the JFrame, the correct uncaughtException handler responds, and i get this output:
> SimpleJFrame uncaughtException handler
However, if i press the button more than once, the main default uncaughtException handler responds, and i get this output:
>Main uncaughtException handler
Is this a bug or am i doing something wrong? the SimplJFrame uncaughtException should be called in my opinion.
All help appreciate!
public class MainClient implements UncaughtExceptionHandler
{
public static void main(String[] args) {
new MainClient();
}
public MainClient() {
Thread.setDefaultUncaughtExceptionHandler(this);
System.out.println("thread main: " + Thread.currentThread());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
SimpleJFrame frame = new SimpleJFrame();
frame.setVisible(true);
}
});
}
public void uncaughtException(Thread thread, Throwable throwable) {
System.out.println("Main uncaughtException handler");
}
}
public class SimpleJFrame extends JFrame implements UncaughtExceptionHandler
{
public SimpleJFrame() {
Thread.currentThread().setUncaughtExceptionHandler(this);
JButton b = new JButton("press me");
b.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent e)
{
getContentPane().add((Component)null);
}
});
this.getContentPane().add(b);
}
public void uncaughtException(Thread thread, Throwable throwable) {
System.out.println("SimpleJFrame uncaughtException handler");
}
}
When an exception occurs on the event dispatch thread, that thread dies and a new one is started. Since you used the non-static setUncaughtExceptionHandler method to set the handler on that thread, that handler dies along with the thread. When the second exception occurs, it's handled by the default handler that you set with the setDefaultUncaughtExceptionHandler method.
Please use [code][/code] tags when you post source code.
http://forum.java.sun.com/help.jspa?sec=formatting
Thanks for the fast response, and sorry for not using code tags (will do in the future).
I'm following your answer, but i'm still a little confused. If I use the defaultExceptionHandler, i don't know which frame the exception occured in (assuming that i have several jframes opened)... Therefore a static uncaughtExceptionHandler will make it difficult.
How can the thread die without bringing down the jframe itself? It did not register the exceptionhandler for the event thread, but the jframe itself.... or?
Is it possible to re-register the uncaughtExceptionHandler for the died thread?
> Wondering if there is a bug in how uncaughtException
> is called?
Unless you are a java programming guru, please don't call program hiccoughs java bugs. 99.99% of the time, the error is with your code. Your suggesting that it may be a java bug will only prove your ignorance and presumptuousness to the others here.
> It did not register the exceptionhandler for the event thread, but the jframe itself....
> or?
You always register these handlers for some thread or other. In your case you call setUncaughtExceptionHandler() inside the SimpleJFrame constructor. But this constructor itself was called on the EDT - because you called it from within SwingUtilities.invokeLater() in the other constructor. Hence you are registering the exception handler for the EDT and when this thread dies and is replaced you end up with only your default handler.
You could have the button's action listener set the uncaught exception handler itself:public SimpleJFrame() {
JButton b = new JButton("press me");
b.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
Thread.currentThread().setUncaughtExceptionHandler(SimpleJFrame.this);
getContentPane().add((Component)null);
}
});
this.getContentPane().add(b);
}
You haven't said why you want to handle uncaught exceptions, rather than merely ... catch them. Especially those on the EDT which could be thrown from anywhere, and involve anything. Perhaps you could find another way to do whatever it is that you want to do.
> Is it possible to re-register the uncaughtExceptionHandler for the died thread?
I don't think that will help. You will always end up with one exception handler for the entire EDT, and that handler will recieve the exceptions from all of the frames. (As well as other stuff.) For what it's worth you can handle EDT exceptions yourself by setting the sun.awt.exception.handler property.public class MainClient implements UncaughtExceptionHandler {
public static void main(String[] args) {
System.setProperty("sun.awt.exception.handler", "EDTEx");
new MainClient();
}
// etc...
}
public class EDTEx {
public void handle(Throwable t) {
System.err.println("EDTx: " + t);
}
}
Now repeated button clicks are all reported the same way:thread main: Thread[main,5,main]
EDTx: java.lang.NullPointerException
EDTx: java.lang.NullPointerException
EDTx: java.lang.NullPointerException
EDTx: java.lang.NullPointerExceptionIt really does seem that the easiest way of catching exceptions that are frame related is to explicitly catch them in the action listener - possibly using a method of the frame to do something with them.public SimpleJFrame() {
JButton b = new JButton("press me");
b.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
try {
getContentPane().add((Component)null);
} catch(Exception ex) {
uncaughtException(Thread.currentThread(), ex);
}
}
});
this.getContentPane().add(b);
}
Sorry for asking if it was a bug. My intension was merly to attract interest. Will avoid the phrase in the future.
Good suggestion to set the handler in the actionPerformed, but i'm not able to do that. Can explain why i want to handle uncaught exceptions, like pbrockway2 requested.
I have a app which loads modules, third parties, and each is presented in its own Jframe. I'd like to catch uncaughtExceptions for each jframe, so i know which module throw an exception. By using a default uncaught exception handler, it seems difficult to figure out which module throw the exception. Can analyze the stack, but i don't know if this is bulletproff?
As I understand it, the purpose of a default exception handler is to make sure the exceptions get logged before your app goes blooie. It's a last resort. What you should be looking at is a logging framework. The java.util.logging package will probably suffice, but I believe Apache log4j gives you finer control over the logging process, should you need it.