aspose file tools*
The moose likes Java in General and the fly likes Runtime Exception not stopping JVM/debugger when using SwingWorker Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Runtime Exception not stopping JVM/debugger when using SwingWorker" Watch "Runtime Exception not stopping JVM/debugger when using SwingWorker" New topic
Author

Runtime Exception not stopping JVM/debugger when using SwingWorker

Derik Davenport
Ranch Hand

Joined: May 30, 2011
Posts: 54
Shouldn't unhandled runtime exceptions cause the JVM (or at least the debugger) to halt and show a stack trace? Shouldn't that be true even when running in a background task? Details of my situation follow.

I have a method in a class that relies on one of the fields being initialized before it is called.
I had a mistake in my code such that the field was initialized with null. In my code, I should have checked that before the method started to do stuff, but I failed to do this because at the time I wrote the method, there was no chance it would be null.

At some point a SwingWorker called this method when the field was null. I would expect a null pointer exception to occur. It does. I would ALSO expect the program to stop immediately (crash) and to get a log of the error in the system output window. This does not happen. Even in the (netbeans) debugger.

Instead what happens is that the SwingWorker thread silently terminates. This makes it really hard to find out where things went bad because I have no idea where the problem occurred or even what problem occurred. The program just keeps running as if no error happened! So I am thinking everything went off without a hitch until at some point much further down the line I find that some other code, that indirectly relied on that background task, doesn't behave the way I expected it to behave.

Is there something I am doing wrong? Is this related to the fact that the method called is inside a SwingWorker? Is there something I am supposed to do to cause that exception to be 'caught' and debugging information displayed? Java requires that all non-runtime exceptions be explicitly caught (or stated as being thrown in the method signature). But run time exceptions (such as null pointer) basically cause no visible indication that they occur.


Thanks in advance for your support.

Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

You'll find that code isn't running in the "main" thread of your program, and that's why exceptions in that code don't cause the application to end. You'll find that to be the case even when a debugger isn't involved -- unless you can see where System.err is being written to, those exceptions will just vanish and all you will see is that your application runs strangely. So yeah, sometimes you don't even know that's happening until you see strange GUI behaviour.

I'm not familiar with the Netbeans debugger but I do use the Eclipse debugger. I assume they are pretty similar from a functional point of view. If that's the case then your debugger should be showing you a list of active threads in one of its windows. You should be able to put a breakpoint on code which is run in a SwingWorker and you should be able to step through that code and see the exception being thrown.

Also (at least based on what I see in Eclipse) when you run your application from Netbeans, there should be a window somewhere which displays stack traces for those "ignored" exceptions.
Derik Davenport
Ranch Hand

Joined: May 30, 2011
Posts: 54
Thanks Paul for the quick reply.

I admit that wasn't really the answer I was hoping for.

I hunted around and found that NetBeans also has something that shows threads (but they are not on by default). But again, when a thread cashes by exception it doesn't show useful debugging information.

In the end I decided to monitor the proper completion of all background tasks. This can be done easily with SwingWorkers by forcing the object creating the new thread to implement PropertyChangeListener and then adding some boiler plate code.




I would have preferred a setting in the debugger to pause execution at an exception, but I guess I this method is more flexible and might have future uses later.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19670
    
  18

Paul Clapham wrote:unless you can see where System.err is being written to, those exceptions will just vanish and all you will see is that your application runs strangely.

Unfortunately, it's worse. For exceptions thrown from event handlers they are printed, yes. But as Derik mentioned, any exception thrown from a SwingWorker's doInBackground() method is silently ignored - it's not even printed to System.err. I found out the hard way only last week...


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Rob Spoor wrote:But as Derik mentioned, any exception thrown from a SwingWorker's doInBackground() method is silently ignored - it's not even printed to System.err. I found out the hard way only last week...

You can set your own exception handler for these exceptions with Thread.setDefaultUncaughtExceptionHandler.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Derik Davenport wrote:I would have preferred a setting in the debugger to pause execution at an exception, but I guess I this method is more flexible and might have future uses later.

NetBeans (and most other debuggers I believe) has a way to set a breakpoint on the occurence of an exception. Go to Windows/Debugging/Breakpoints, right click in window that appears and choose New Breakpoint. Choose Exception as the breakpoint type. There are some settings (most important is the class name - including packages - of the exception you want to break on, eg. java.lang.NullPointerException, or * to match any exception). Experiment with the settings, there is also help available (press F1).

I personally don't use these breakpoints much, though - with a stack trace, I know where the exception has occurred and it seems more useful to me to step through the code, so that I can see whats happening in the program before the exception itself occurs.

Either way, you'll probably want to install an uncaught exception handler in your application (see above) so that you don't have to add try/catch everywhere only to log the exception.
Derik Davenport
Ranch Hand

Joined: May 30, 2011
Posts: 54
Martin Vajsar wrote:
You can set your own exception handler for these exceptions with Thread.setDefaultUncaughtExceptionHandler.


I am not sure how to use this. I created a class that implements Thread.UncaughtExceptionHandler. Then in doInBackground (which should be running in the thread whose exceptions are otherwise silently dropped), I added the line



But when the runtime exception occurs within doInBackground, MyHandler.uncaughtException is never called.



Should I have put the line for aforementioned code in the main thread that created the SwingWorker?

Derik Davenport
Ranch Hand

Joined: May 30, 2011
Posts: 54
Martin Vajsar wrote:
Go to Windows/Debugging/Breakpoints, right click in window that appears and choose New Breakpoint. Choose Exception as the breakpoint type. .... Experiment with the settings, there is also help available (press F1).



Perhaps it is just user error, but this doesn't seem to be working in the way I would expect or in a way that would be useful.

I have created an (intentional) NullPointerException within my doInBackground() method.


If I configure the breakpoint to stop on "caught" exceptions then it will stop on line 2. But if I configure it to stop on caught exceptions it also triggers on NullPointerExceptions (and every other exception) that are correctly caught (and optionally handled) in a try/catch construct.

It seems to me that since this NullPointer is NOT in a try/catch it should be considered an uncaught exception.

Perhaps it has something to do with the way background threads work or in particular how SwingWorker threads work so that the debugger considers this exception to be a caught exception even when I have not provided a try/catch construct. Perhaps this thread's thread pool or something else specifies its own defaultUncaughtException handler. That would explain why my Thread.setUncaughtExceptionHanddler(eh) (see above) attempt did not work either.

In that case, Swing should provide some way to override that default catcher because it doesn't do much except exit silently and that is annoying. I still haven't reliably found a way to catch an exception running in SwingWorker except the boiler plate above (which gives a stack trace) so that I can go back and use the debugger to step through it. But it would be much better if I could stop the debugger right at the point of exception so that I don't have to go back and try to reproduce the error after setting a bunch of manual break points.


Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Derik Davenport wrote:But when the runtime exception occurs within doInBackground, MyHandler.uncaughtException is never called.

Ahh, I'm sorry, I overlooked this. You're right. I've revisited my project and I see I'm using SwingWorker in the following way. I have an abstract class with the following code snippet, all background actions inherit from it and override the doExecute() method:

There is some more code, but this is the gist of it. I don't need to handle exceptions anywhere else, therefore I've forgotten about it a bit :)

Then there is also exception handler for Evetnt Dispatch Thread, but this code comes form a colleague of mine and I don't know whether it could not cause problems on other platforms (works with Oracle's Java 6 on Windows). It is called at the program startup:

Also don't know whether this by chance would not handle exceptions from SwingWorkers.
Derik Davenport
Ranch Hand

Joined: May 30, 2011
Posts: 54
Martin,

I think I can see how your system work. This would not stop the debugger but, like the system I discussed before with the property change listener, it would cause any uncaught exceptions to show.
But could I not achieve the same result by simply overriding the Done method like so?




Using your system I would need to remember to call super.done() in my own overrides of the done() method.

I guess it is kind of akward to stick my code into every Done statement. But other than that, are there other advantages to your system?

IN particular, does this relate to the fact that MyHandler.uncheckedException(e) was not being called?

Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Derik,

I didn't answer fully yesterday, it was quite late in my time zone.

Breakpoint problem is caused by the fact that Swing handles exceptions somewhere in its code. If it didn't, the Event Dispatch Thread would terminate if an unhandled exception occurred in it. This causes both problems: the exception is not passed to the Thread.setDefaultUncaughtExceptionHandler() handler (because it is caught somewhere), and the breakpoint does not fire if set to caught mode, for precisely the same reason. (It's long time since I've stopped using Exception breakpoints and now I recall it was because I had run into the same problems as you did.)

Overriding the done() method to catch exceptions is not enough. That method is called from the Event Dispatch Thread. If the exception is thrown in the doInBackground() method, it is in fact thrown in a different thread. The try/catch statement cannot catch exceptions that occurred in a different thread.

My class is a little bit more complicated than shown here. It actually has three abstract methods: doStart(), doExecute(), doFinish(). The doStart() and doFinish() methods are called from Event Dispatch Thread - doStart() is called just before the code snippet I've posted, doFinish() is called from done() (only if swe is null). As they are abstract, I cannot forget to implement them and, since exceptions are already handled, I can put just the functionality I need there and don't have to mess with (runtime) exceptions. This is the main advantage of this system.

I cannot easily post full code here, as it has more complicated structure (it has evolved in time a bit) and frankly, it would sorely need some refactoring.

I've also googled a bit about the sun.awt.exception.handler property: this probably handles just the exceptions thrown in the Event Dispatch Thread. It probably saves you from the need to catch unchecked exceptions in every action listener you use, but I've not found anything indicating it would also handle SwingWorkers. Plus, it ties you to Sun/Oracle JVMs. Exceptions in Swing are pretty complicated beasts, it seems.
Derik Davenport
Ranch Hand

Joined: May 30, 2011
Posts: 54
Martin Vajsar wrote:
This causes both problems: the exception is not passed to the Thread.setDefaultUncaughtExceptionHandler() handler (because it is caught somewhere), and the breakpoint does not fire if set to caught mode, for precisely the same reason.


I think you mean "the breakpoint does not fire unless it is set to caught mode". And yes, I agree that would explain it.


Overriding the done() method to catch exceptions is not enough. That method is called from the Event Dispatch Thread. If the exception is thrown in the doInBackground() method, it is in fact thrown in a different thread. The try/catch statement cannot catch exceptions that occurred in a different thread.


True, but SwingWorker saves the exceptions that occurs during doInBackground in a field called exception. (I think). When you call swingWorker.get() from done() and the field called exception is not null, then the SwingWorker object will throw the ExecutionException with the original exception as the cause. That is why I the last argument in the second Logger statement is ex.getCause().

My cluttering up the done() statement every time lacks the finesse of your system. And without that your other bit of code for catching exceptions in the EDT, (System.setProperty("sun.awt.exception.handler", MyExceptionHandler.class.getName());, my system only shows the error on the SystemOut, and doesn't stop the debugger or anything like that. With your system, I could put a standard breakpoint in the done() fucntion where it throws the exception.

I cannot easily post full code here, as it has more complicated structure (it has evolved in time a bit) and frankly, it would sorely need some refactoring.


I appreciate the thought, but please don't trouble yourself to refactor code on my account. In my original research for this problem I came across this page that something like the doStart() method. http://www.baptiste-wicht.com/2010/09/a-better-swingworker/

Exceptions in Swing are pretty complicated beasts, it seems.

Yes, I am beginning to think I shouldn't have posted this in the beginners forum. But at the time, I thought this was just my ignorance of how to use my IDE or some easy (but not obvious) bit of exception handling in Java. No matter, it probably happens all the time.

Again, thanks for all your help, your code, and your follow ups. I will have to implement something like this myself.


Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Derik Davenport wrote:I think you mean "the breakpoint does not fire unless it is set to caught mode".

Yes, exactly.

True, but SwingWorker saves the exceptions that occurs during doInBackground in a field called exception. (I think). When you call swingWorker.get() from done() and the field called exception is not null, then the SwingWorker object will throw the ExecutionException with the original exception as the cause.

Didn't know this. Nice, thanks.

With your system, I could put a standard breakpoint in the done() fucntion where it throws the exception.

Not exactly. At that time the execution context of the exception is long gone - you're now in a different thread. It is not possible to inspect local variables and so on at this stage. When I need to debug the exception, I try to figure out the immediate conditions that made the exception happen (usually a stack trace and a good look at the code is enough) and create a conditional breakpoint there (sometimes I put the condition just to the code and set a normal breakpoint in the "true" branch, its in the end less fiddly than creating true conditional breakpoint).

I appreciate the thought, but please don't trouble yourself to refactor code on my account.

No, the refactoring is badly needed in its own right. I've also learned something new in this thread since I've written it, I just need to find time to do it.

Thanks for sharing your experience.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38363
    
  23
Moving thread as too difficult for "beginning".
Derik Davenport
Ranch Hand

Joined: May 30, 2011
Posts: 54
Martin Vajsar wrote:Not exactly. At that time the execution context of the exception is long gone - you're now in a different thread. It is not possible to inspect local variables and so on at this stage.


Oh yes. To be sure I can't actually debug the exception there. But at least I know there WAS an exception. I know exactly what I was doing when the exception occurred. And I even get a stack trace of exactly where it broke down _and_ why it broke down (which exception was thrown). Before this, I might have gone 20 minutes before I even suspected that something screwy was going on. And by then I had no clue as to what had happened, when it happened, or even where!

As for me, I already had a base class that overrode SwingWorker and added the functionality that is common to all my background tasks (such as message handling with other threads). I overrode the done function in that class and made it final. The new done calls get() in a try/catch. If the try succeeds it calls a new function called "finish()". The finish() method in the base class does nothing but can be overridden by the child classes (sub-classes / inheriting classes - whatever they call them in Java) in the same way that done() was used previously. If the try fails, then the catch for the ExecutionException sends the stack trace to System out, and it puts an alert on the screen (just in case I miss the output). Swallowed exceptions is such an annoying bug, and this trick is so easy to implement (code wise there is nothing new here) that it could/should? be covered in the tutorials.

I also created a NetBeans Exception break point for caught ExecutionExceptions in my base class. Not really necessary at this point but still kind of cool when I am still in the debugger stage.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

I'll revisit this topic one last time (I hope):
Derik Davenport wrote:Oh yes. To be sure I can't actually debug the exception there. But at least I know there WAS an exception.

You should definitely inform the user about an error that occurred with a message box or something. You certainly want to be informed about it even when you're not debugging. It is easy as the done() method is on Event Dispatch Thread, the message box can be shown right from there. It seemed so self-evident to me that I didn't mention it earlier.

I actually display a form that says some unspecific text like 'An error occured' and contains a Details... button which shows the stack trace. This way users can easily mail in the stack trace, which is often enough to identify the problem.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: Runtime Exception not stopping JVM/debugger when using SwingWorker