Opened 12 years ago

Closed 10 years ago

#379 closed defect (fixed)

Investigate various graph window exceptions

Reported by: Kevin Milner Owned by:
Priority: major Milestone:
Component: commons Version:
Keywords: Cc:

Description

We have been noticing various graph window exceptions lately. Some of them do not even contain any OpenSHA classes in the stack trace. Some are fatal, some are not.

Lets use this ticket to catalog the various exceptions encountered, and document how they happened (in order to figure out the problem).

For starters:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
	at java.lang.System.arraycopy(Native Method)
	at javax.swing.text.BoxView.updateLayoutArray(BoxView.java:197)
	at javax.swing.text.BoxView.replace(BoxView.java:168)
	at javax.swing.text.View.append(View.java:401)
	at javax.swing.text.FlowView$FlowStrategy.layout(FlowView.java:456)
	at javax.swing.text.FlowView.layout(FlowView.java:184)
	at javax.swing.text.BoxView.setSize(BoxView.java:380)
	at javax.swing.text.BoxView.updateChildSizes(BoxView.java:349)
	at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:331)
	at javax.swing.text.BoxView.layout(BoxView.java:691)
	at javax.swing.text.BoxView.setSize(BoxView.java:380)
	at javax.swing.plaf.basic.BasicTextUI$RootView.setSize(BasicTextUI.java:1703)
	at javax.swing.plaf.basic.BasicTextUI.getPreferredSize(BasicTextUI.java:901)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1634)
	at javax.swing.JEditorPane.getPreferredSize(JEditorPane.java:1412)
	at javax.swing.ScrollPaneLayout.layoutContainer(ScrollPaneLayout.java:769)
	at java.awt.Container.layout(Container.java:1421)
	at java.awt.Container.doLayout(Container.java:1410)
	at java.awt.Container.validateTree(Container.java:1507)
	at java.awt.Container.validateTree(Container.java:1513)
	at java.awt.Container.validateTree(Container.java:1513)
	at java.awt.Container.validate(Container.java:1480)
	at org.opensha.sha.gui.infoTools.GraphWindow.togglePlot(GraphWindow.java:454)
	at org.opensha.sha.gui.infoTools.GraphWindow.drawGraph(GraphWindow.java:428)
	at org.opensha.sha.gui.infoTools.GraphWindow.setXAxisLabel(GraphWindow.java:529)
	at org.opensha.sha.gui.infoTools.GraphiWindowAPI_Impl.setX_AxisLabel(GraphiWindowAPI_Impl.java:179)
	at scratch.UCERF3.FaultSystemSolution.plotPaleoObsAndPredPaleoEventRates(FaultSystemSolution.java:599)
	at scratch.UCERF3.inversion.RunInversion.<init>(RunInversion.java:258)
	at scratch.UCERF3.inversion.RunInversion.<init>(RunInversion.java:120)
	at scratch.UCERF3.inversion.RunInversion.<init>(RunInversion.java:63)
	at scratch.UCERF3.inversion.RunInversion.main(RunInversion.java:491)
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException
	at java.lang.System.arraycopy(Native Method)
	at javax.swing.text.BoxView.updateLayoutArray(BoxView.java:197)
	at javax.swing.text.BoxView.replace(BoxView.java:168)
	at javax.swing.text.View.append(View.java:401)
	at javax.swing.text.FlowView$FlowStrategy.layout(FlowView.java:456)
	at javax.swing.text.FlowView.layout(FlowView.java:184)
	at javax.swing.text.BoxView.setSize(BoxView.java:380)
	at javax.swing.text.BoxView.updateChildSizes(BoxView.java:349)
	at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:331)
	at javax.swing.text.BoxView.layout(BoxView.java:691)
	at javax.swing.text.BoxView.setSize(BoxView.java:380)
	at javax.swing.plaf.basic.BasicTextUI$RootView.setSize(BasicTextUI.java:1703)
	at javax.swing.plaf.basic.BasicTextUI$RootView.paint(BasicTextUI.java:1422)
	at javax.swing.plaf.basic.BasicTextUI.paintSafely(BasicTextUI.java:723)
	at javax.swing.plaf.basic.BasicTextUI.paint(BasicTextUI.java:870)
	at javax.swing.plaf.basic.BasicTextUI.update(BasicTextUI.java:849)
	at javax.swing.JComponent.paintComponent(JComponent.java:752)
	at javax.swing.JComponent.paint(JComponent.java:1029)
	at javax.swing.JComponent._paintImmediately(JComponent.java:5098)
	at javax.swing.JComponent.paintImmediately(JComponent.java:4882)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:812)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:714)
	at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:694)
	at javax.swing.RepaintManager.access$700(RepaintManager.java:41)
	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1672)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:677)
	at java.awt.EventQueue.access$000(EventQueue.java:85)
	at java.awt.EventQueue$1.run(EventQueue.java:638)
	at java.awt.EventQueue$1.run(EventQueue.java:636)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:647)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException
	at java.lang.System.arraycopy(Native Method)
	at javax.swing.text.BoxView.updateLayoutArray(BoxView.java:196)
	at javax.swing.text.BoxView.replace(BoxView.java:168)
	at javax.swing.text.FlowView$FlowStrategy.layout(FlowView.java:466)
	at javax.swing.text.FlowView.layout(FlowView.java:184)
	at javax.swing.text.BoxView.setSize(BoxView.java:380)
	at javax.swing.text.BoxView.updateChildSizes(BoxView.java:349)
	at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:317)
	at javax.swing.text.BoxView.layout(BoxView.java:692)
	at javax.swing.text.BoxView.setSize(BoxView.java:380)
	at javax.swing.plaf.basic.BasicTextUI$RootView.setSize(BasicTextUI.java:1703)
	at javax.swing.plaf.basic.BasicTextUI.getPreferredSize(BasicTextUI.java:901)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1634)
	at javax.swing.JEditorPane.getPreferredSize(JEditorPane.java:1412)
	at javax.swing.ScrollPaneLayout.layoutContainer(ScrollPaneLayout.java:769)
	at java.awt.Container.layout(Container.java:1421)
	at java.awt.Container.doLayout(Container.java:1410)
	at java.awt.Container.validateTree(Container.java:1507)
	at java.awt.Container.validate(Container.java:1480)
	at javax.swing.RepaintManager.validateInvalidComponents(RepaintManager.java:670)
	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1671)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:677)
	at java.awt.EventQueue.access$000(EventQueue.java:85)
	at java.awt.EventQueue$1.run(EventQueue.java:638)
	at java.awt.EventQueue$1.run(EventQueue.java:636)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:647)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0
	at javax.swing.text.BoxView.layoutMinorAxis(BoxView.java:824)
	at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:327)
	at javax.swing.text.BoxView.layout(BoxView.java:691)
	at javax.swing.text.FlowView.layout(FlowView.java:203)
	at javax.swing.text.BoxView.setSize(BoxView.java:380)
	at javax.swing.text.BoxView.updateChildSizes(BoxView.java:349)
	at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:331)
	at javax.swing.text.BoxView.layout(BoxView.java:691)
	at javax.swing.text.BoxView.setSize(BoxView.java:380)
	at javax.swing.plaf.basic.BasicTextUI$RootView.setSize(BasicTextUI.java:1703)
	at javax.swing.plaf.basic.BasicTextUI.getPreferredSize(BasicTextUI.java:901)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1634)
	at javax.swing.JEditorPane.getPreferredSize(JEditorPane.java:1412)
	at javax.swing.ScrollPaneLayout.layoutContainer(ScrollPaneLayout.java:769)
	at java.awt.Container.layout(Container.java:1421)
	at java.awt.Container.doLayout(Container.java:1410)
	at java.awt.Container.validateTree(Container.java:1507)
	at java.awt.Container.validate(Container.java:1480)
	at javax.swing.RepaintManager.validateInvalidComponents(RepaintManager.java:670)
	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1671)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:677)
	at java.awt.EventQueue.access$000(EventQueue.java:85)
	at java.awt.EventQueue$1.run(EventQueue.java:638)
	at java.awt.EventQueue$1.run(EventQueue.java:636)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:647)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Change History (4)

comment:1 Changed 12 years ago by Kevin Milner

I have recently come across another exception that I researched a bit. I believe the problem is similar to this stack exchange posting.

Basically bad things happen when you interact with java GUIs in a non AWT/Swing thread. Ideally every time we interact with GUI code we should make sure to be in a AWT/Swing thread. This includes constructors for new GUI elements, parameter editor refreshes, setting things like x/y log or axis on a plot, anything really. In practice this is a huuuuuuge pain and makes code less readable. First of all you have to surround all such code in statements like this:

SwingUtilities.invokeAndWait(new Runnable() {
	@Override
	public void run() {
		// GUI code
	}
});

You can also use SwingUtilities?.invokeLater if you don't need to block the current thread until that code gets executed. This gets even more frustrating because every variable referenced inside the run() method must be final (or a global class variable).

My inclination is to modify code to use this method on an as needed basis. This is going to be too frustrating, time consuming, and flat out nasty to implement everywhere. Peter: thoughts?

comment:2 Changed 12 years ago by Peter Powers

Nice work/research. I've actually had some musings about this recently. I believe that our applications once all extended Applet which may have ensured execution on the EDT, but I'm not sure. In their current state, I believe there is a high probability that they are executed on the EDT, but it is not guaranteed. As a first step, we can guarantee EDT execution by wrapping all 'main' entry points thusly (and as noted in the StackExchange? post):

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            ...
        }
    });
}

There shouldn't be any problems with final variables and such. Temblor executes this way (SCEC-VDO should too) and I don't have to declare anything final. It will also be ok to do almost everything in our apps on the EDT.

Now, the worst offender when it comes to threading is the calculation progress bar, there may be others. I forget the details but IIRC it creates a separate thread for its timer that isn't even a capital T Timer; instead it sleeps 200ms in a while loop and checks the progress of a calculation (that is occurring on the EDT or whatever current thread) to update the gui. It's effed up. The correct approach is for hazard calculations (or whatever other calculation) to be done off the EDT. Although one can roll one's own, there is the highly useful SwingWorker? class. Anything that extends SwingWorker? can be listened to, can get() a result from (with this method blocking/waiting until the task completes), can be canceled etc. We can talk more about solutions.

comment:3 Changed 12 years ago by Kevin Milner

Peter, I agree that most of our application code is already executing on the EDT - anything that is initiated by a click (and not explicitly forked elsewhere) would run in the EDT (probably only initial application constructors and setup would not run in the EDT). I was more talking about small test applications when I said it was a huge hassle - such as a simple little main method that calculates something where you want to pop open a graph window at the end. That's where we're seeing the bulk of these exceptions. It's frustrating in that case to wrap things in invokeLater or invokeAndWait calls. For example you might have to do the following:

Here's an example that I just modified to use it:

...
CPT tempCPT = GMT_CPT_Files.MAX_SPECTRUM.instance();
CPTVal last = tempCPT.remove(tempCPT.size()-1);
final CPT threadCPT = tempCPT.rescale(1, 8);
last.start = 8f;
last.end = 23f;
threadCPT.add(last);

final int avgNumX = 400;
final int targetPPM = 2;

SwingUtilities.invokeAndWait(new Runnable() {
	
	@Override
	public void run() {
		try {
			generatePlots(tsaDir, dsaDir, highlight, coolType, threads, nodes,
					includeStartSubZero, plotAvg, bundleDsaBySubs, bundleTsaBySubs,
					avgNumX, targetPPM, true, plots, threadCPT);
		} catch (Exception e) {
			ExceptionUtils.throwAsRuntimeException(e);
		}
	}
});

Making everything final can be annoying (especially if one of your variables is set in an if statement). We also have an issue here with exceptions - you can't make run() throw anything, so any exception will have to be dealt with inside the run() method or thrown as a runtime exception.

In these cases I'll probably just deal with random exceptions rather than waste time bullet proofing little test classes.

comment:4 Changed 10 years ago by Kevin Milner

Resolution: fixed
Status: newclosed

Ned was seeing a lot of these errors and I think it's the same cause, modifying things like axis labels and font sizes from the main thread instead of the EDT. I went ahead and surrounded pretty much everything in GraphWindow? with SwingUtilities?.invokeAndWait(...) and the problems seem to have stopped. We usually use that class from non-interactive tester classes which causes these frequent issues. Marking as closed, committed in [10424].

Note: See TracTickets for help on using tickets.