JVxTable ArrayIndexOutOfBoundsException

Allgemeine Fragen zur Entwicklung von und mit JVx.

JVxTable ArrayIndexOutOfBoundsException

Postby manfrede » Mon Jun 02, 2014 5:54 pm

Hallo!

Ich bin mit meinem Latein am Ende. Das Ticketsystem zu unserem Problem hätte ich bereits durchsucht, jedoch nichts passendes gefunden. Auch bin ich mir nicht sicher, ob es sich überhaupt um einen JVx Bug handelt.

Also versuche ich mein Glück mal hier, vielleicht ergibt sich ja was.

Das Setting:

Ein Teil unsere neuen Applikation stellt ein Software-Terminal dar. Dieses läuft – überwacht von einem anderen Programm – durchgängig.
Prinzipiell ist die Applikation nach wie vor Forms, nur die Hauptmaske wurde durch einen WorkScreen ersetzt.
Auf diesem befindet sich physisch nur eine Tabelle, wenn auch unsichtbar (für Debugzwecke bzw. Expertenmodus).
Diese Tabelle wird durch ein MemDataBook gespeist. Die Rowdefinition setzt sich aus genau 4 Spalten zusammen. In den meisten Fällen befinden sich nicht einmal Daten darin.
Die Applikation läuft einem Windows 7 Rechner mit Java 1.7.0_55.

Initialisierung:

Code: Select all
  private void initializeModel() throws Exception {
    RowDefinition rd = new RowDefinition();
    rd.addColumnDefinition(new ColumnDefinition("PIN"));
    rd.addColumnDefinition(new ColumnDefinition("WERT"));
    rd.addColumnDefinition(new ColumnDefinition("APNR"));
    rd.addColumnDefinition(new ColumnDefinition("APSPLITTNR"));

    mdbMDEDaten = new MemDataBook(rd);
    mdbMDEDaten.setName("MDE-DataBook");
    mdbMDEDaten.open();
  }

  protected void initializeUI() throws Exception {
    this.setLayout(new UIBorderLayout());
    UITable table = new UITable();
    table.setEditable(false);
    table.setDataBook(mdbMDEDaten);
    this.add(table, UIBorderLayout.CENTER);
  }


Danach wird auf dem Databook nur mehr ab und zu ein Datensatz hinzugefügt.

Das Problem:

Nach einigen Tagen wirft die Applikation jedoch einen Fehler:
Code: Select all
java.lang.ArrayIndexOutOfBoundsException: 3 >= 3
        at java.util.Vector.elementAt(Unknown Source)
        at javax.swing.table.DefaultTableColumnModel.getColumn(Unknown Source)
        at com.sibvisions.rad.ui.swing.ext.JVxTable$DataBookTableColumnModel.getColumn(JVxTable.java:2258)
        at javax.swing.JTable$2.getMidPointAt(Unknown Source)
        at javax.swing.JTable.adjustSizes(Unknown Source)
        at javax.swing.JTable.setWidthsFromPreferredWidths(Unknown Source)
        at javax.swing.JTable.doLayout(Unknown Source)
        at com.sibvisions.rad.ui.swing.ext.JVxTable$1.doLayout(JVxTable.java:222)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validateTree(Unknown Source)
        at java.awt.Container.validate(Unknown Source)
        at oracle.forms.handler.ComponentItem.doAutoScroll(Unknown Source)
        at oracle.forms.handler.ComponentItem.onUpdate(Unknown Source)
        at oracle.forms.handler.TextComponentItem.onUpdate(Unknown Source)
        at oracle.forms.handler.TextFieldItem.onUpdate(Unknown Source)
        at oracle.forms.handler.UICommon.onUpdate(Unknown Source)
        at oracle.forms.engine.Runform.onUpdateHandler(Unknown Source)
        at oracle.forms.engine.Runform.processMessage(Unknown Source)
        at oracle.forms.engine.Runform.processSet(Unknown Source)
        at oracle.forms.engine.Runform.onMessageReal(Unknown Source)
        at oracle.forms.engine.Runform.sendDeferredMessages(Unknown Source)
        at oracle.forms.engine.Runform.onMessage(Unknown Source)
        at oracle.forms.engine.Heartbeat.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)


terminalerr.png
terminalerr.png (367.36 KiB) Viewed 11793 times


Das Problem wird also ausgelöst durch eine Forms-Message auf ein Textfield. Diese validiert den gesamten Komponenten-Baum durch und löst auf der JTable ein Layouting aus.

Inspektion:

Eine Heapdump-Analyse vor und nach dem Fehler bringt keinen Erfolg, metadata, columnModel als auch die columnView sprechen von jeweils 4 Spalten.

heapdump.png
heapdump.png (77.18 KiB) Viewed 11793 times


Das einzige, das ich mir erklären könnte ist die Tatsache, dass das Ganze nicht auf dem AWTEventThread läuft, und sich deshalb mit diesem spießen könnte, dementsprechend also eine "Race"-Condition.

Was mich daran stört ist jedoch folgendes:
In der Methode setWidthsFromPreferredWidths der JTable wird bereits die Anzahl an Spalten abgeholt über die eine Methode später in adjustSizes drübergeloopt wird.
Es müsste sich also genau in der Zwischenzeit das TableColumnModel ändern.

Leider sind Untersuchungen in dieser Gegend ziemlich mühselig, da das Problem nur alle paar Tage bei durchgehendem Lauf auftritt.

Ich wüsste nicht wie ich dem vorbeugen könnte.
manfrede
 
Posts: 21
Joined: Tue Oct 22, 2013 11:45 am

Re: JVxTable ArrayIndexOutOfBoundsException

Postby mhandsteiner » Mon Jun 02, 2014 7:06 pm

Was mir dazu einfällt, ist, dass OracleForms eventuell in einem eigenen Thread, und nicht im AWT Thread den Komponentenbaum validiert.

Es kann fast nur ein Multithreading Problem sein.

Dieses Problem müsste dann mit einem synchronized der Funktion initTableColumns gelöst sein.

Wenn möglich, zum Testen bitte einmal folgendes probieren:

private synchronized void initTableColumns(boolean pForceUpdate)
mhandsteiner
 
Posts: 14
Joined: Mon Sep 28, 2009 2:17 pm

Re: JVxTable ArrayIndexOutOfBoundsException

Postby manfrede » Tue Jun 03, 2014 9:10 am

Das werde ich mal versuchen, danke!
manfrede
 
Posts: 21
Joined: Tue Oct 22, 2013 11:45 am

Re: JVxTable ArrayIndexOutOfBoundsException

Postby manfrede » Thu Jun 05, 2014 9:34 am

Leider hat das wie vermutet einen Deadlock verursacht:

Code: Select all
Found one Java-level deadlock:
=============================
"HeartBeat":
  waiting to lock monitor 0x08383fcc (object 0x2ac8d508, a com.sibvisions.rad.ui.swing.ext.JVxTable$DataBookTableColumnModel),
  which is held by "AWT-EventQueue-0"
"AWT-EventQueue-0":
  waiting to lock monitor 0x04d30944 (object 0x29919ae0, a java.awt.Component$AWTTreeLock),
  which is held by "HeartBeat"

Java stack information for the threads listed above:
===================================================
"HeartBeat":
   at com.sibvisions.rad.ui.swing.ext.JVxTable$DataBookTableColumnModel.initTableColumns(JVxTable.java:2560)
   - waiting to lock <0x2ac8d508> (a com.sibvisions.rad.ui.swing.ext.JVxTable$DataBookTableColumnModel)
   at com.sibvisions.rad.ui.swing.ext.JVxTable$DataBookTableColumnModel.getColumns(JVxTable.java:2292)
   at javax.swing.plaf.basic.BasicTableUI.getPreferredSize(Unknown Source)
   at javax.swing.JComponent.getPreferredSize(Unknown Source)
   at com.sibvisions.rad.ui.swing.ext.JVxTable$1.getPreferredSize(JVxTable.java:227)
   at javax.swing.ScrollPaneLayout.layoutContainer(Unknown Source)
   at de.javasoft.plaf.synthetica.SyntheticaScrollPaneLayoutManager.layoutContainer(SyntheticaScrollPaneLayoutManager.java:40)
   at java.awt.Container.layout(Unknown Source)
   at java.awt.Container.doLayout(Unknown Source)
   at java.awt.Container.validateTree(Unknown Source)
   at java.awt.Container.validateTree(Unknown Source)
   at java.awt.Container.validateTree(Unknown Source)
   at java.awt.Container.validateTree(Unknown Source)
   at java.awt.Container.validateTree(Unknown Source)
   at java.awt.Container.validateTree(Unknown Source)
   at java.awt.Container.validateTree(Unknown Source)
   at java.awt.Container.validateTree(Unknown Source)
   at java.awt.Container.validateTree(Unknown Source)
   at java.awt.Container.validateTree(Unknown Source)
   at java.awt.Container.validateTree(Unknown Source)
   at java.awt.Container.validateTree(Unknown Source)
   at java.awt.Container.validate(Unknown Source)
   - locked <0x29919ae0> (a java.awt.Component$AWTTreeLock)
   at oracle.forms.handler.ComponentItem.doAutoScroll(Unknown Source)
   at oracle.forms.handler.ComponentItem.onUpdate(Unknown Source)
   - locked <0x2af4d4d0> (a oracle.forms.handler.TextFieldItem)
   at oracle.forms.handler.TextComponentItem.onUpdate(Unknown Source)
   - locked <0x2af4d4d0> (a oracle.forms.handler.TextFieldItem)
   at oracle.forms.handler.TextFieldItem.onUpdate(Unknown Source)
   - locked <0x2af4d4d0> (a oracle.forms.handler.TextFieldItem)
   at oracle.forms.handler.UICommon.onUpdate(Unknown Source)
   - locked <0x2af4d4d0> (a oracle.forms.handler.TextFieldItem)
   at oracle.forms.engine.Runform.onUpdateHandler(Unknown Source)
   at oracle.forms.engine.Runform.processMessage(Unknown Source)
   at oracle.forms.engine.Runform.processSet(Unknown Source)
   at oracle.forms.engine.Runform.onMessageReal(Unknown Source)
   at oracle.forms.engine.Runform.sendDeferredMessages(Unknown Source)
   at oracle.forms.engine.Runform.onMessage(Unknown Source)
   at oracle.forms.engine.Heartbeat.run(Unknown Source)
   at java.lang.Thread.run(Unknown Source)
"AWT-EventQueue-0":
   at java.awt.Component.invalidate(Unknown Source)
   - waiting to lock <0x29919ae0> (a java.awt.Component$AWTTreeLock)
   at java.awt.Container.invalidate(Unknown Source)
   at javax.swing.JComponent.revalidate(Unknown Source)
   at javax.swing.JLabel.setText(Unknown Source)
   at com.sibvisions.rad.ui.swing.ext.JVxTable$GenericTableCellHandler.getTableCellRendererComponent(JVxTable.java:2765)
   at com.sibvisions.rad.ui.swing.ext.JVxTable$DataBookTableColumnModel.findOrCreateTableColumn(JVxTable.java:2466)
   at com.sibvisions.rad.ui.swing.ext.JVxTable$DataBookTableColumnModel.initTableColumns(JVxTable.java:2608)
   - locked <0x2ac8d508> (a com.sibvisions.rad.ui.swing.ext.JVxTable$DataBookTableColumnModel)
   at com.sibvisions.rad.ui.swing.ext.JVxTable$DataBookTableColumnModel.access$800(JVxTable.java:1977)
   at com.sibvisions.rad.ui.swing.ext.JVxTable.doRepaint(JVxTable.java:1658)
   at com.sibvisions.rad.ui.swing.ext.JVxTable.run(JVxTable.java:390)
   at java.awt.event.InvocationEvent.dispatch(Unknown Source)
   at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
   at java.awt.EventQueue.access$200(Unknown Source)
   at java.awt.EventQueue$3.run(Unknown Source)
   at java.awt.EventQueue$3.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
   at java.awt.EventQueue.dispatchEvent(Unknown Source)
   at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
   at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
   at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
   at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
   at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
   at java.awt.EventDispatchThread.run(Unknown Source)


Ich werde mal versuchen, soweit wie möglich alle AWT-Funktionen, welche über die Bean (erst ab hier läuft ja der WorkScreen) laufen abzufangen (validate, invalidate etc.) und bei
Code: Select all
!EventQueue.isDispatchThread()

diese einfach in ein invokeLater einpacken.
manfrede
 
Posts: 21
Joined: Tue Oct 22, 2013 11:45 am

Re: JVxTable ArrayIndexOutOfBoundsException

Postby mhandsteiner » Thu Jun 05, 2014 11:12 am

Im AWT Thread bleiben ist sicher die beste Lösung.

folgendes könnte man auch noch probieren:

Folgenden Befehl in der Funktion findOrCreateTableColumn auskommentieren oder löschen:
(In der aktuellen Version Zeile 2450)

tableColumns.remove(i);
mhandsteiner
 
Posts: 14
Joined: Mon Sep 28, 2009 2:17 pm


Return to Entwicklung