Community
Participate
Working Groups
Build Identifier: M20110210-1200 In this method, private void updateChildren(Widget widget, Object parent, Object[] elementChildren, boolean updateLabels), I am getting a SWTException when refreshing a tree viewer, it is not easily reproducible but I will try to describe what I have observed. I inspect the code and I found a place that may cause problems. IN the following snippet, // dispose of surplus items, optimizing for the case where elements have // been deleted but not reordered, or all elements have been removed. int numItemsToDispose = items.length - min; if (numItemsToDispose > 0) { CustomHashtable children = newHashtable(elementChildren.length * 2); for (int i = 0; i < elementChildren.length; i++) { Object elementChild = elementChildren[i]; children.put(elementChild, elementChild); } int i = 0; while (numItemsToDispose > 0 && i < items.length) { Object data = items[i].getData(); if (data == null || items.length - i <= numItemsToDispose || !children.containsKey(data)) { if (data != null) { disassociate(items[i]); } items[i].dispose(); if (i + 1 < items.length) { // The components at positions i+1 through // items.length-1 in the source array are copied into // positions i through items.length-2 System.arraycopy(items, i + 1, items, i, items.length - (i+1)); } numItemsToDispose--; } else { i++; } } } The line, System.arraycopy(items, i + 1, items, i, items.length - (i+1)), can cause problem. For example, when you currently have 17 items and need to dispose the last 5 items. The arraycopy method does not move the items up. Instead, it just copy the items at the end of the array to the item position where the item is disposed. So the length always stays at 17. It copies the reference (see screenshots) and so I end up having 3 same item in my array at position 15, 16, 17. Next time, when it processes item #15 and disposes it, the item at 15, 16, 17 are all disposed because it they are all referencing the same element. Then when the code do item.getData() on these items, I am getting a SWTException. Reproducible: Sometimes Steps to Reproduce: I cannot reproduce this problem in Eclipse only, but I can reproduce the problem every time with my project in IBM Integration Developer. Let me know if you want to see this problem in IBM Integration Developer. If you want to reproduce the problem yourself, you need IBM Integration Developer, Monitor Toolkit and BPM Process Center Server Advanced 7.5.1. Let me know if you want to setup the environment.
Created attachment 203933 [details] Breakpoint stopped before arraycopy is run for the first time. This is captured when the code dispose an item in the array the first time.
Created attachment 203934 [details] Breakpoint after arraycopy is run In this screenshot, you can see that item # 15 and #16 is the same after the copy. For now, all items in the array is still valid.
Created attachment 203935 [details] Breakpoint after arraycopy is run for the second time You can see that item #14, #15, #16 in the array is referencing the same item. For now, the items in the array are still valid.
Created attachment 203936 [details] Breakpoint before arraycopy is run for the third time This time, the while loop is processing item #14. It is disposed and so item #14, #15, #16 are all disposed. When the while loop continue to run to process the rest of the items in the array, I get a SWTException because the call, item[i].getData() found the item is already disposed.
Moving to UI for comments.
The local variable numItemsToDispose should work as a guard against this. At the start "items" array: (numItemsToDispose =3 ) 14 - points to A 15 - points to B 16 - points to C 1st iteration: i = 14; A is disposed; "items" array is 14 - points to B 15 - points to C 16 - points to C and numItemsToDispose = 2 2nd iteration: i = 14; B is disposed; "items" array is 14 - points to C 15 - points to C 16 - points to C and numItemsToDispose = 1 3rd iteration: i = 14; C is disposed; "items" array is 14 - points to C 15 - points to C 16 - points to C cycle breaks as numItemsToDispose == 0 It does not seem that the issue is in the System.arraycopy(). Are there any local variables that guard the cycle are calculated improperly? I presume you override AbstractTreeViewer#getChildren(). Does the override reuse returned array? Could you check by making it return a clone?
Which version of Eclipse are you using? 3.7.1?
I'm using Eclipse 3.6.2 and we did not override the getChildren method. Today, I cannot reproduce the problem anymore, but I still wonder if there is any chance that your code will attempt to dispose an already disposed item. Let me know what you think. I'm OK to close this issue now until I see it again. Thanks.
Flannan, I'll mark this as FIXED for now...if you ever see it occurring in a later release please feel free to re-open it...thanks.