Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4074274

Calls to remove inside of removenotify cause wrong components to be removed

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Won't Fix
    • Icon: P4 P4
    • None
    • 1.1.4, 1.1.8_003, 1.3.0
    • client-libs
    • 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;
      }

            son Oleg Sukhodolsky (Inactive)
            tyao Ting-Yun Ingrid Yao (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: