-
Bug
-
Resolution: Won't Fix
-
P4
-
None
-
1.1.4, 1.1.8_003, 1.3.0
-
generic, x86
-
generic, windows_nt
ingrid.yao@Eng 1997-08-25
Oracle reported:
If, inside of removeNotify(), code gets executed that calls remove()
on the container from which the first component was getting removed,
it is possible for the wrong component to be removed from the
container's component array.
The problem is that after calling removeNotify(), remove(int i)
assumes the index is still valid. Either the component must be
removed from the component array before calling removeNotify()
(which would be a change in semantics and break backwards compatibility),
or the index must be re-computed after calling removeNotify(), and
the code should handle the possibility that, in removeNotify(),
the component might have already been removed.
The sample code repros the problem.
TEST CASE
Press the button.
Only the blue button should get removed, and, visually
it seems like that happens. But, after pressing the button,
dump the component hierarchy (control-alt-F1); _both_
components are gone. Even worse, removeNotify() got called
_twice_ on the blue component, but never got called on
the red component. So, since its a heavyweight component,
it's still visible, and can never be removed.
[This example does seem contrived, but it closely mirrors
a situation that happened in our code, minus a lot of
intervening code]
import java.awt.*;
import java.awt.event.*;
public class RemoveBug extends Frame implements ActionListener
{
static public void main(String[] args)
{
(new RemoveBug()).setVisible(true);
}
public RemoveBug()
{
setLayout(new FlowLayout());
add(new ScrewyComponent(Color.blue));
add(new ScrewyComponent(Color.red));
Button b = new Button("Press me");
b.addActionListener(this);
add(b);
pack();
}
public void actionPerformed(ActionEvent e)
{
remove(0); // Remove the blue component
}
}
class ScrewyComponent extends Canvas
{
public ScrewyComponent(Color c)
{
setBackground(c);
}
public void removeNotify()
{
if(!_removed)
{
removed = true; // Don't infinite loop...
/ Now, remove myself again
ontainer parent = getParent();
arent.remove(this); //Note this isn't by index
}
super.removeNotify();
}
public Dimension getPreferredSize()
{
return new Dimension(50, 50);
}
private boolean _removed;
}