Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

any recommendations?

3 views
Skip to first unread message

Brandon McCombs

unread,
Feb 4, 2007, 8:16:16 PM2/4/07
to
Hello,

Somewhere in my code I have a bug that I can't reliably reproduce. It
occurs randomly when I'm deleting entries from a JList (I retrieve
certain pieces of info from the entry before deleting it, then I delete
it and the JList contents are then refreshed so remaining items are
re-added to the JList). The only output I get when the exception occurs
is the following:

Exception in thread "AWT-EventQueue-0"
java.lang.ArrayIndexOutOfBoundsException: 1 >= 0
at java.util.Vector.elementAt(Unknown Source)
at javax.swing.DefaultListModel.getElementAt(Unknown Source)
at javax.swing.plaf.basic.BasicListUI.paintCell(Unknown Source)
at javax.swing.plaf.basic.BasicListUI.paint(Unknown Source)
at javax.swing.plaf.ComponentUI.update(Unknown Source)
at javax.swing.JComponent.paintComponent(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintWithOffscreenBuffer(Unknown Source)
at javax.swing.JComponent.paintDoubleBuffered(Unknown Source)
at javax.swing.JComponent._paintImmediately(Unknown Source)
at javax.swing.JComponent.paintImmediately(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at
javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown
Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(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)


The "1" as the index value differs between exception printouts. I don't
know where that index value is originating from or what Vector is really
having its elements retrieved. The index value doesn't correspond to
the index of the Object that I'm selecting for deletion. I've placed
try/catches throughout the places where I thought was causing the
exception to print out a stacktrace that I hoped would include a line
number but I'm not getting any extra output. I also would put in a print
statement so I knew which try/catch was being executed but I don't see
that outputted either.

When the JList is refreshed it is done so through a thread. I've tried
to use run() to make the thread do its work but not in a thread and I
don't get the exception but since I can't reproduce it reliably I don't
know if it's really a threading problem or not. Using Eclipse's
debugger also doesn't help so far because I can't get the error to occur
during the debugging, at least not yet.

Is there anything else I can try that can give me more information as to
what line in my code this is occurring on so I can begin to fix it?

thanks

Knute Johnson

unread,
Feb 4, 2007, 8:28:12 PM2/4/07
to

Are you modifying the JList on the EDT? Are you modifying the Vector
after creating your JList? Can you make a simple test program that
demonstrates the problem?

--

Knute Johnson
email s/nospam/knute/

Brandon McCombs

unread,
Feb 4, 2007, 9:07:03 PM2/4/07
to
Knute Johnson wrote:
> Brandon McCombs wrote:
>> Hello,
>>
>> Somewhere in my code I have a bug that I can't reliably reproduce. It
>> occurs randomly when I'm deleting entries from a JList (I retrieve
>> certain pieces of info from the entry before deleting it, then I
>> delete it and the JList contents are then refreshed so remaining items
>> are re-added to the JList). The only output I get when the exception
>> occurs is the following:
>>
>> Exception in thread "AWT-EventQueue-0"
>> java.lang.ArrayIndexOutOfBoundsException: 1 >= 0
>> at java.util.Vector.elementAt(Unknown Source)
>> at javax.swing.DefaultListModel.getElementAt(Unknown Source)
>> at javax.swing.plaf.basic.BasicListUI.paintCell(Unknown Source)
>> at javax.swing.plaf.basic.BasicListUI.paint(Unknown Source)
[snip]

>>
>>
>> The "1" as the index value differs between exception printouts. I
>> don't know where that index value is originating from or what Vector
>> is really having its elements retrieved. The index value doesn't
>> correspond to the index of the Object that I'm selecting for deletion.
>> I've placed try/catches throughout the places where I thought was
>> causing the exception to print out a stacktrace that I hoped would
>> include a line number but I'm not getting any extra output. I also
>> would put in a print statement so I knew which try/catch was being
>> executed but I don't see that outputted either.
>>
>> When the JList is refreshed it is done so through a thread. I've tried
>> to use run() to make the thread do its work but not in a thread and I
>> don't get the exception but since I can't reproduce it reliably I
>> don't know if it's really a threading problem or not. Using Eclipse's
>> debugger also doesn't help so far because I can't get the error to
>> occur during the debugging, at least not yet.
>>
>> Is there anything else I can try that can give me more information as
>> to what line in my code this is occurring on so I can begin to fix it?
>>
>> thanks
>
> Are you modifying the JList on the EDT? Are you modifying the Vector
> after creating your JList? Can you make a simple test program that
> demonstrates the problem?
>

The code that the Thread class uses to tell the JList when to update is
this:

SwingUtilities.invokeLater(new Runnable() {
public void run() {
component.updateGUI(results);
component.resetGUI(results);
}
});

Component is the class that contains my GUI which is a JTree and JList
in a JSplitPane; component is passed into the Thread's constructor.

Results is a Vector that contains the results of a LDAP search which
will be put into the JList.

Yes I'm modifying the Vector. Since the JList can have entries
added/modified/removed the Vector will obviously be changed accordingly
(as I state in the original mesg). I can't make a simple test program
because I don't know where the problem is. If I did I wouldn't have
posted this because I'd be working on figuring out a way to fix it. The
problem could be in a lot of places and ripping out stuff to duplicate
the problem would be a waste of time I believe since I can't reproduce
it not to mention the code involved is spread across multiple classes.
To test it I'm having to create temporary entries in my LDAP server and
then delete them one by one to see if the error occurs. Sometimes I
delete 50 before it crops up, other times I delete 1 and the index value
mentioned in the exception never corresponds with the deleted entry.

I'm mainly asking if there is a way to glean more info from the
exception information. I can't believe it isn't giving me a line number
to review. Is the printout I originally posted the only stack trace
information available from the JVM? I've put whole method bodies in a
try/catch and I don't get any more information so either I won't get
more information or I'm putting try/catches in the wrong place. Can the
JVM be launched with options that will help?

Brandon

Knute Johnson

unread,
Feb 4, 2007, 11:54:50 PM2/4/07
to

Brandon:

I think you are attempting to access a non-existing element or you've
been modifying the Vector itself which is not good either. If you want
to add and remove elements from a JList you need to use a ListModel that
is read/write. So since you can't make a test program, shows us
snippets of the critical code where you create the JList and modify it.

Brandon McCombs

unread,
Feb 5, 2007, 12:52:00 AM2/5/07
to

Well the deletion still works when I get the exception. I am doing the
deletion by going through the ListModel for the JList which I thought
was correct. I never knew you could create a read-only ListModel.

I use the following as the constructor to my BrowserModel class which
contains 2 models for my Browser (JTree and JList I mentioned before):

public BrowserModel(Node root) {
this.root = (Node)root.getChildAt(0);
tree = new DefaultTreeModel(root);
list = new DefaultListModel();
}

The method I call for deleting a selected item from the JList is the
following (model is the instance of BrowserModel):

private void list_deleteObj() {
int idx = dirList.getSelectedIndex();
String dn = LDAPMgr.ldapUtility.getDN(
model.getListModel().getElementAt(idx) );
int ans = JOptionPane.showConfirmDialog(this,
"Confirm delete for:\n" + dn + "\n",
"Delete Object", JOptionPane.YES_NO_OPTION,
JOptionPane.PLAIN_MESSAGE);
if (ans == 1)
return;
String msg = null;
msg = LDAPMgr.ldapUtility.deleteEntry(
model.getListModel().getElementAt(idx));
/* if successful */
if (msg == null) {
model.getListModel().remove(idx);
/* reload the subtree and list to show deletion */
refresh();
}
}

The idx in the code above rarely matches (if ever) the index value
listed in the generated exception and again, the deletion above still
works when the exception is generated. Refresh() essentially determines
which node in the JTree needs refreshing and then calls expand(node,
node.getDN()). Expand() removes all the node's current children and
spawns the thread to retrieve the current children. The items in the
JList are the children of the selected Node in the JTree.

The thread is spawned with this:

selectedNode = node;
searchBase = dn;
if (asyncSearch != null)
asyncSearch.stopSearch(); //allow 1 search at a time
asyncSearch = new AsyncSearch(this);
asyncSearch.setSearchBase(searchBase);
asyncSearch.setFilter("(objectClass=*)");
asyncSearch.setReturnedAttributes("*");
asyncSearch.setScope(1);
asyncSearch.start();

That calls a method that executes a LDAP search and passes the results
back to the Browser class by calling updateGUI() from the Browser.
Within updateGUI() the Browser populates the selected node's children in
the JTree as well as the JList (which is just another view of the node's
children). If I do this whole process enough times I get the
aforementioned exception.

I hope that description is helpful and understandable.
If you can figure this one out I'd appreciate it because I don't even
know where to look since nothing is making sense (index values not
matching up, deletion still works).


thanks for the help

Knute Johnson

unread,
Feb 5, 2007, 1:33:00 AM2/5/07
to

Brandon:

I don't see anything there, nothing looks out of the ordinary. Any
chance that you've got a concurrency problem? Or maybe you are setting
the size of the ListModel before trying to remove the element?

I think this is going to be hard to find without a simpler test program.
I had a problem like that once though that I couldn't duplicate. I
ended up solving it by synchronizing access to the method where I
thought the problem was occurring. That was kind of a shotgun approach.

Sorry I can't be more help.

Michael Rauscher

unread,
Feb 5, 2007, 7:00:19 AM2/5/07
to
Brandon McCombs wrote:
>>>>>
>>>>> Exception in thread "AWT-EventQueue-0"
>>>>> java.lang.ArrayIndexOutOfBoundsException: 1 >= 0
>>>>> at java.util.Vector.elementAt(Unknown Source)
>>>>> at javax.swing.DefaultListModel.getElementAt(Unknown Source)
>>>>> at javax.swing.plaf.basic.BasicListUI.paintCell(Unknown Source)
>>>>> at javax.swing.plaf.basic.BasicListUI.paint(Unknown Source)
>>> [snip]
> Well the deletion still works when I get the exception. I am doing the
> deletion by going through the ListModel for the JList which I thought
> was correct. I never knew you could create a read-only ListModel.

NB: a ListModel *is* read-only by default.

>
> The method I call for deleting a selected item from the JList is the
> following (model is the instance of BrowserModel):
>
> private void list_deleteObj() {

Is this method called from the EDT?

>
> The idx in the code above rarely matches (if ever) the index value
> listed in the generated exception and again, the deletion above still
> works when the exception is generated. Refresh() essentially determines

Sure, the exception originates from the UI-Delegate's paint method. Why
would you expect the deletion not to work?

The reason for the exception is usually a simple one: you're modifying
the underlying ListModel in one thread while the EDT repaints the list.

Imagine the following pseudo code as part of the painting procedure:

int n = model.getSize();
for ( int i = 0; i < n; i++ ) {
// ...
Object value = model.getElementAt(i);
// ...
}

Let's consider a ListModel that contains 5 elements. The code above runs
on the EDT, so it starts with n = 5 and enters the loop. Now, in another
thread you delete one element from the ListModel so that
model.getSize()==4. The loop continues until i=4, then an
ArrayIndexOutOfBoundsException will be thrown, e.g.: 4 >= 4. If the
second thread would have removed all elements from the ListModel, the
exception is thrown immediately at the next model.getElementAt method
call, e. g. 2 >= 0.

>
> The thread is spawned with this:
>

...
> asyncSearch = new AsyncSearch(this);
...
> asyncSearch.start();

Does AsynchSearch modify the ListModel? And if, how?

Bye
Michael

Nigel Wade

unread,
Feb 5, 2007, 7:34:27 AM2/5/07
to
Brandon McCombs wrote:


> The method I call for deleting a selected item from the JList is the
> following (model is the instance of BrowserModel):
>
> private void list_deleteObj() {
> int idx = dirList.getSelectedIndex();
> String dn = LDAPMgr.ldapUtility.getDN(
> model.getListModel().getElementAt(idx) );
> int ans = JOptionPane.showConfirmDialog(this,
> "Confirm delete for:\n" + dn + "\n",
> "Delete Object", JOptionPane.YES_NO_OPTION,
> JOptionPane.PLAIN_MESSAGE);
> if (ans == 1)
> return;
> String msg = null;
> msg = LDAPMgr.ldapUtility.deleteEntry(
> model.getListModel().getElementAt(idx));
> /* if successful */
> if (msg == null) {
> model.getListModel().remove(idx);
> /* reload the subtree and list to show deletion */
> refresh();
> }
> }
>

What thread is the above method being executed on? If it's not the EDT you have
a problem there, you are modifying the JList in a thread other than the EDT.

The error is telling you that when the EDT came to draw a JList it tried to
access element 1 and that element didn't exist in the the DefaultListModel's
Vector at the time. That would imply a synchronization error, the Vector is in
the process of being modified whilst it's being drawn (the JList and
DefaultTreeModel have a different idea of how many elements there are), and I
don't see how that can happen unless it's being modified from another thread -
even the EDT can only do one thing at a time...

--
Nigel Wade, System Administrator, Space Plasma Physics Group,
University of Leicester, Leicester, LE1 7RH, UK
E-mail : n...@ion.le.ac.uk
Phone : +44 (0)116 2523548, Fax : +44 (0)116 2523555

Brandon McCombs

unread,
Feb 5, 2007, 9:33:44 AM2/5/07
to
Michael Rauscher wrote:
> Brandon McCombs wrote:
>>>>>>
>>>>>> Exception in thread "AWT-EventQueue-0"
>>>>>> java.lang.ArrayIndexOutOfBoundsException: 1 >= 0
>>>>>> at java.util.Vector.elementAt(Unknown Source)
>>>>>> at javax.swing.DefaultListModel.getElementAt(Unknown Source)
>>>>>> at javax.swing.plaf.basic.BasicListUI.paintCell(Unknown Source)
>>>>>> at javax.swing.plaf.basic.BasicListUI.paint(Unknown Source)
>>>> [snip]
>> Well the deletion still works when I get the exception. I am doing the
>> deletion by going through the ListModel for the JList which I thought
>> was correct. I never knew you could create a read-only ListModel.
>
> NB: a ListModel *is* read-only by default.
>
>>
>> The method I call for deleting a selected item from the JList is the
>> following (model is the instance of BrowserModel):
>>
>> private void list_deleteObj() {
>
> Is this method called from the EDT?

currently it is not.


>
>>
>> The idx in the code above rarely matches (if ever) the index value
>> listed in the generated exception and again, the deletion above still
>> works when the exception is generated. Refresh() essentially determines
>
> Sure, the exception originates from the UI-Delegate's paint method. Why
> would you expect the deletion not to work?

I never said I didn't expect it to work. I was notifying you guys that
it still was in case you didn't know and needed to know.

>
> The reason for the exception is usually a simple one: you're modifying
> the underlying ListModel in one thread while the EDT repaints the list.
>
> Imagine the following pseudo code as part of the painting procedure:
>
> int n = model.getSize();
> for ( int i = 0; i < n; i++ ) {
> // ...
> Object value = model.getElementAt(i);
> // ...
> }
>
> Let's consider a ListModel that contains 5 elements. The code above runs
> on the EDT, so it starts with n = 5 and enters the loop. Now, in another
> thread you delete one element from the ListModel so that
> model.getSize()==4. The loop continues until i=4, then an
> ArrayIndexOutOfBoundsException will be thrown, e.g.: 4 >= 4. If the
> second thread would have removed all elements from the ListModel, the
> exception is thrown immediately at the next model.getElementAt method
> call, e. g. 2 >= 0.

ok that makes sense.

>
>>
>> The thread is spawned with this:
>>
> ...
>> asyncSearch = new AsyncSearch(this);
> ...
>> asyncSearch.start();
>
> Does AsynchSearch modify the ListModel? And if, how?

no. It calls updateGUI() from the component that spawned the thread.
Component is a constructor to that thread class and updateGUI() is an
interface method of an interface I created for that purpose of letting
the components (I got 3 of them) update themselves in their own ways.
Only one of them is involved with this problem though. I'll work on
making the delete method spawn from the EDT.

I don't suppose you guys know of a way I can test this to know for sure
it works?

>
> Bye
> Michael

Brandon McCombs

unread,
Feb 5, 2007, 9:38:45 AM2/5/07
to

It's possible b/c like I said, I can't get it to work in Eclipse's
debugger and maybe the breakpoints I sort of straightening everything
out while being debugged. Well I don't specifically set it. To remove
the current items before I retrieve the most current children for the
selected tree node I call model.getListModel().removeAllElements(). Then
the search is executed and the newest data is put back into the list one
by one by looping through the Vector of results returned from the search.

>
> I think this is going to be hard to find without a simpler test program.
> I had a problem like that once though that I couldn't duplicate. I
> ended up solving it by synchronizing access to the method where I
> thought the problem was occurring. That was kind of a shotgun approach.

I've been setting synchronized keyword on some methods. I'll need to
keep doing that in case it helps but without a sure fire way of testing
this I may never really know if it's fixed.

Chris Uppal

unread,
Feb 5, 2007, 10:38:08 AM2/5/07
to
Brandon McCombs wrote:

> Is there anything else I can try that can give me more information as to
> what line in my code this is occurring on so I can begin to fix it?

People downthread are already speculating that the problem is caused by
modifying the model from outside the EDT; I suspect that they are correct.

I just wanted to add (for general info) that the version of rt.jar which comes
with the JRE is (at least in 1.5 and 1.6 on my machine) compiled without line
numbers -- whence the less informative stack trace. The equivalent rt.jar
which is part of the JRE which is inside the JDK /does/ have that information
(again, as far as I can tell from what's on my machine). So if you can use
that JRE to execute your program, instead of the "standard" one, then you may
get more information.

-- chris


Brandon McCombs

unread,
Feb 5, 2007, 7:00:07 PM2/5/07
to

Well I've gotten line numbers printed before but for some reason in this
case (when I really need it) the line number doesn't get printed. I've
been using the JRE included with Eclipse 3.1.2 but I just tried using
JDK 1.5 and it didn't help make line numbers visible (running it outside
of Eclipse as a regular JAR).

Brandon McCombs

unread,
Feb 5, 2007, 7:19:11 PM2/5/07
to

Maybe I did this wrong but in the place in my code where I call the
method above I put the following:

SwingUtilities.invokeLater(new Runnable() {
public void run() {

list_deleteObj(); }
});

And I still get the exception generated so what am I missing?

Brandon McCombs

unread,
Feb 5, 2007, 7:25:56 PM2/5/07
to


Although what you say makes sense, I wonder if it's my problem because
I'm modifying the model outside of the EDT (whatever that situation is
properly termed) and after a few other method calls is when the model is
updated with new nodes. I don't know when the exception actually occurs
(painting when the item is deleted or painting when i refresh the list
to get the current contents from the server) so maybe your theory is
still accurate.

private void list_deleteObj() {
int idx = dirList.getSelectedIndex();
String dn = LDAPMgr.ldapUtility.getDN(
model.getListModel().getElementAt(idx) );
int ans = JOptionPane.showConfirmDialog(this,
"Confirm delete for:\n" + dn + "\n",
"Delete Object",
JOptionPane.YES_NO_OPTION,
JOptionPane.PLAIN_MESSAGE);
if (ans == 1)
return;
String msg = null;
msg = LDAPMgr.ldapUtility.deleteEntry(
model.getListModel().getElementAt(idx));
/* if successful */
if (msg == null) {
model.getListModel().remove(idx);
/* reload the subtree and list to show deletion */
refresh();
}
}

As you can see the removal from the list occurs before refresh(). In
refresh() I call expand(). In expand() I spawn the thread to refresh the
list model. If the repaint from the model.getListModel().remove(idx);
doesn't occur until my thread is spawned then maybe that creates the
exception. In another posting a few minutes before this one I tell
Nigel that I put the call to the method above on the EDT and it didn't
help; after enough deletions the exception crops up again.

Michael Rauscher

unread,
Feb 6, 2007, 2:49:46 AM2/6/07
to
Brandon McCombs schrieb:

> Although what you say makes sense, I wonder if it's my problem because
> I'm modifying the model outside of the EDT (whatever that situation is
> properly termed) and after a few other method calls is when the model is
> updated with new nodes.

If you modfy the model outside of the EDT, then it's the problem. It's
easy. Really. Don't modify UI-state outside of the EDT and you don't get
strange Exceptions :)

I'll explain it in more detail, e. g. have a look at

> model.getListModel().remove(idx);
> /* reload the subtree and list to show deletion */
> refresh();

Since you're using DefaultListModel, the element at index idx gets
removed from DefaultListModel's data Vector. Then, the model's listeners
(to which the JList belongs, too) get notified. The JList repaints itself.

You call refresh afterwards. I expect, you set a new Vector on the
DefaultListModel. I expect that this occurs outside of the EDT, too.


Now, I can imagine two situations:
1) remove was called while repaint was active
2) refresh() modified the ListModel while repaint was active.
E. g. refresh could call DefaultListModel#removeAll.

>
> As you can see the removal from the list occurs before refresh().

Doesn't matter. The point is, that you modify UI-state outside of the
EDT. There are only a few methods in Swing (e. g. repaint()) that may be
used outside the EDT.

Bye
Michael

Michael Rauscher

unread,
Feb 6, 2007, 2:53:27 AM2/6/07
to
Brandon McCombs schrieb:

Look out for other threads. What does e. g. AsynchSearch do?

Bye
Michael

Brandon McCombs

unread,
Feb 6, 2007, 10:03:34 AM2/6/07
to

It retrieves the current state of what the list should contain by
contacting an LDAP server. It then alerts the GUI the results are ready
by calling the GUI's updateGUI() method by I do that on the EDT like
above so it should be okay.

What I ended up doing that seems to work so far is I put the body of the
method prepareGUI() inside of the SwingUtilities.invokeLater() call.
The prepareGUI() is called by asyncSearch to prepare the GUI before the
newest results are loaded. prepareGUI() is actually what deletes the
rest of the items in the listmodel so that I don't get duplicate entries
when it is updated. I've been testing that and haven't received the
exception, yet.

Michael Rauscher

unread,
Feb 6, 2007, 5:29:06 PM2/6/07
to
Brandon McCombs wrote:
>>> And I still get the exception generated so what am I missing?
>>
>> Look out for other threads. What does e. g. AsynchSearch do?
>>
>
> It retrieves the current state of what the list should contain by
> contacting an LDAP server. It then alerts the GUI the results are ready
> by calling the GUI's updateGUI() method by I do that on the EDT like
> above so it should be okay.
>
> What I ended up doing that seems to work so far is I put the body of the
> method prepareGUI() inside of the SwingUtilities.invokeLater() call.
> The prepareGUI() is called by asyncSearch to prepare the GUI before the
> newest results are loaded. prepareGUI() is actually what deletes the
> rest of the items in the listmodel so that I don't get duplicate entries
> when it is updated. I've been testing that and haven't received the
> exception, yet.

Sounds good. Next time don't follow the trial and error method: just
ensure that any code that modifies the GUI runs on the EDT.

Bye
Michael

0 new messages