Skip to main content

Netbeans, Swing, and runtime exceptions

10 replies [Last post]
countsessine
Offline
Joined: 2007-06-13
Points: 0

This seems like a trivial problem, but I haven't been able to find this out either by searching this forum or through a google search, so I'm going to ask...

How do I break on exceptions that happen in the Swing EDT? If I have an actionlistener that gets called, say on a button press, and I do something silly in the handler that's going to generate a runtime exception, how do I break on that, by default, in the NetBeans debugger?

When I try it, all that happens is a stack trace is printed out in the output window. Swing seems to be catching and killing any runtime exceptions I generate and I don't get a chance to see them in the debugger.

How do I set up NetBeans/swing/the VM/whatever to actually break on the site of the exception? Without enabling first-chance exception breakpoints, of course?

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
countsessine
Offline
Joined: 2007-06-13
Points: 0

That's excactly what I'm doing now, but the whole point is to see the locals at the site of the exception, the way you can in MFC, WinForms, Qt, GTK, or any other GUI toolkit ever created. I don't want to see the locals in EventDispatchThread.run() in Swing's message pump. I want to see *my* locals, where I screwed up.

Obviously there has to be a mechanism for developers to catch and gracefully handle all uncaught exceptions in a shipping app (if only to tell the customer to email you some debugging info). But to force this behavior on programmers in development? If the code in EventDispatchThread.run does what I think it does, they've basically put a try-catch-finally block around the whole event dispatch call. Why?

[i][/i][i][/i][i][/i][b][/b][b][/b][u][/u][b][/b]

countsessine
Offline
Joined: 2007-06-13
Points: 0

Indeed - I do know how to set exception breakpoints - the problem has more to do with Swing than NetBeans, really.

Try creating the GUIFormExamples sample program in NetBeans. In the Antenna.java class, add an ActionPerformed event handler to one of the buttons. Then something that'll generate a runtime exception. You could do this, for example:

int[] arr = new int[2];
arr[3] = 0;

Then create a runtime exception breakpoint. Push the button. Does NetBeans break on the "arr[3] = 0" statement? No.

In OS X, it doesn't break at all. Instead, the stack trace is printed out on the output console. (!!!) The runtime exception never unwinds far enough for NetBeans to get it. In Windows, it breaks on a function at the base of the EDT, presumeably it's message pump, EventDispatchThread.run(). Obviously the ActionEvent handler is nowhere to be seen on the callstack.

Clearly this is not the 'right thing to do'. So how do I get the right behavior (a nice callstack leading up to the ActionEvent handler, the site of the runtime exception)?

Message was edited by: countsessine

Message was edited by: countsessine

tball
Offline
Joined: 2003-06-10
Points: 0

What's wrong with exception breakpoints? If you find too many of them are being thrown, perhaps your design is guilty of using exceptions for control flow, which is considered a poor practice. One alternative to consider is setting an exception breakpoint with a condition, so it only breaks when you want it to.

countsessine
Offline
Joined: 2007-06-13
Points: 0

It's not really my design though, it's Swing. And I'm not against exception breakpoints - I'm merely trying to pre-emptively address anyone who says, "set your runtime exception breakpoint to Caught and Uncaught."

Caught or first-chance exception breakpoints break as soon as an exception is thrown, regardless of whether or not the exception will be caught. Uncaught or last-chance exception breakpoints only break when the stack has been completely unwound and there were no try-catch blocks unclosing it.

There's a big usage difference between first-chance and last-chance exceptions and it has to do with catastrophic errors (like runtime exceptions) and expected errors that need to be handled and recovered from as part of normal operation.

You'd never tell your debugger to always break on Caught exceptions because you'll be overwhelmed with breaks. Low-level networking code, for example, is filled with exception throws. Throwing and catching exceptions is just the most elegant way of recovering from networking errors that could happen at any time and in any state during a network operation. The java class loader itself throws a fair number of exceptions that are promptly caught. Try starting up the Antenna.java form in the GUIFormExamples sample code with a Caught And Uncaught Runtime Exception breakpoint. Long before the form is even loaded you'll start breaking on exceptions in ResourceBundle.getObject(). OTOH using a first-chance exception breakpoint would be one way of debugging a spurious exception throw in such code.

A last chance exception breakpoint is something you should be able to keep enabled all the time. Watching for uncaught runtime exceptions is useful. The problem is that Swing seems to catch and re-throw these for some mysterious reason, thwarting any attempt to get a decent stack-trace in the debugger. No locals, more difficult debugging.

Message was edited by: countsessine

tarbo
Offline
Joined: 2006-12-18
Points: 0

A trick (not a pretty one) that I used for a minor Swing application was to attach a custom ExceptionHandler using [i]setDefaultUncaughtExceptionHandler[/i], and then set a breakpoint at entry of its [i]uncaughtException[/i] method. Later on, when out of development and into release, I changed it to a output to a Logger [i]et presto[/i].

The advantage to this technique is that you catch only uncaught exceptions that would otherwise disrupt the thread, and you have the opportunity to act upon the exception. The downside is that, to me, it just doesn't look clean. But that could be me.

Maybe this is more what you are looking for? As far as I know, it should preserve the call stack and locals (though they will be a little deeper down).

darul75
Offline
Joined: 2007-06-14
Points: 0

To detect EDT exception, here code :

At launched, set RepaintManager as this :

RepaintManager.setCurrentManager(new CheckingRepaintManager());

---------------------------------------------------------------------------------------------------------

/**
*

To avoid the possibility of deadlock, you must take extreme care that Swing components and models are created,
* modified, and queried only from the event-dispatching thread (EDT).

*
*/
public class CheckingRepaintManager
extends RepaintManager {

/** The associated logger. */
private static final Logger logger = Logger.getLogger(CheckingRepaintManager.class);

/**
* @see RepaintManager#addDirtyRegion(javax.swing.JComponent, int, int, int, int)
*/
public synchronized void addDirtyRegion(JComponent c, int x, int y, int w, int h) {
this.checkEDTRule(c);
super.addDirtyRegion(c, x, y, w, h);
}

/**
* @see RepaintManager#addInvalidComponent(javax.swing.JComponent)
*/
public synchronized void addInvalidComponent(JComponent invalidComponent) {
this.checkEDTRule(invalidComponent);

super.addInvalidComponent(invalidComponent);
}

protected void checkEDTRule(Component component) {
if (this.violatesEDTRule(component)) {
EDTRuleViolation violation = new EDTRuleViolation(component);

StackTraceElement[] stackTrace = violation.getStackTrace();

try {
for (int e = stackTrace.length - 1; e >= 0; e--) {
if (this.isLiableToEDTRule(stackTrace[e])) {
StackTraceElement[] subStackTrace = new StackTraceElement[stackTrace.length - e];
System.arraycopy(stackTrace, e, subStackTrace, 0, subStackTrace.length);
violation.setStackTrace(subStackTrace);
}
}
}
catch (Exception ex) {
// keep stack trace
}

this.indicate(violation);
}
}

/**
* Display violation message.
*
* @param violation
*/
protected void indicate(EDTRuleViolation violation) {
logger.warn(
"CORRECT ASAP to prevent deadlock: Components and models creation/update/query must be done within EDT.",
violation);
}

protected boolean isLiableToEDTRule(StackTraceElement element)
throws Exception {
return Component.class.isAssignableFrom(Class.forName(element.getClassName()));
}

protected boolean violatesEDTRule(Component component) {
return !SwingUtilities.isEventDispatchThread() && component.isShowing();
}
}

------------------------------------------------------------------------------------------------------

Also u will need to use SwingUtilities.invokeLater() when it is necessary to inject process into in EDT thread....

Message was edited by: darul75

countsessine
Offline
Joined: 2007-06-13
Points: 0

Huh?

sauvage
Offline
Joined: 2004-03-04
Points: 0

In NetBeans, Menu Run, New breakpoint..., Breakpoint Type: Exception, Exception Class Name: RuntimeException.

scamhi
Offline
Joined: 2003-09-16
Points: 0

You might want to try this too, to catch these exceptions during runtime.
You can catch them and popup a dialog box, for example.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4714232

-S

countsessine
Offline
Joined: 2007-06-13
Points: 0

I don't really want to catch these exceptions. Indeed, my whole problem seems to be that Swing has taken the liberty of catching these excpetions for me in EventDispatchThread.run(). I want NetBeans to catch the exceptions, rewind the stack, and show me my locals at the site of the original exception, like any other debugger will do for you.

If this was an issue with an app I was deploying I might want to catch them and handle them gracefully, but in development, if there's a runtime exception, I don't want my UI lib to silently swallow it without telling me which is exactly what seems to be happening.

It's an interesting link, though. It seems they're arguing over the fact that the EDT's exception handler can't be customized. I just want it to go away.

Message was edited by: countsessine