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

Animated GIF in JEditorPane eats CPU when not displayed still

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P3 P3
    • None
    • 1.4.1
    • client-libs



      Name: jk109818 Date: 03/28/2003


      FULL PRODUCT VERSION :
      java version "1.4.1_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
      Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)

      FULL OPERATING SYSTEM VERSION :
      Microsoft Windows 2000 [Version 5.00.2195]

      ADDITIONAL OPERATING SYSTEMS :
      Linux


      A DESCRIPTION OF THE PROBLEM :
      The problem occurs when an animated gif is displayed in a
      JEditorPane under text/html (e.g. img src=".."), and then
      the component is hidden. The GIF continues to eat CPU
      cycles, and the Image Animator thread lives on forever.
      Reference bug 4302818
      (http://developer.java.sun.com/developer/bugParade/bugs/4302
      818.html) which is the same problem, except with JLabel's
      and JButton's.

      The test case loads a JFrame with some buttons. One toggles
      appearance of a JLabel with an animated GIF, one toggles
      appearance of a JEditorPane with an animated GIF. The final
      button lists all the Image Animator threads. Toggling the
      JLabel in and out will create and destroy Image Animator
      threads as expected, but once the JEditorPane creates an
      Image Animator thread it never goes away. I do not include
      animated GIF's with this bug report, but the test case
      references some images on the web. Placing the JEditorPane
      in its own window that gets disposed has no effect, for
      simplicity I did not do that in the test case.

      The solution for bug #4302818 was to add "!isShowing() ||"
      in the if block in imageUpdate for JLabel. A similar
        statement was added to AbstractButton's imageUpdate, so
      that it returns false if the component is not visible. I
      tried this solution with JEditorPane but it was
      unsuccessful... this is (apparently) because the image
      observer for the animated gif in the HTML pane is not the
      JEditorPane itself. I am unsure what class manages the
      images references by HTML in editor panes.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Create and display a JEditorPane referencing an animated
      image.
      2. Hide and destroy the JEditorPane.
      3. Note continued existence of an Image Animator thread.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      The Image Animator thread should go away once the component
      is hidden.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      The Image Animator thread stack trace usually looks like the following:

      "Image Animator 0" daemon prio=4 tid=0x008FF0E8 nid=0x584 waiting on condition
      [d81f000..d81fd8c]
              at java.lang.Thread.sleep(Native Method)
              at sun.awt.image.GifFrame.dispose(Unknown Source)
              at sun.awt.image.GifImageDecoder.readImage(Unknown Source)
              at sun.awt.image.GifImageDecoder.produceImage(Unknown Source)
              at sun.awt.image.InputStreamImageSource.doFetch(Unknown Source)
              at sun.awt.image.ImageFetcher.fetchloop(Unknown Source)
              at sun.awt.image.ImageFetcher.run(Unknown Source)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.Component;
      import java.awt.FlowLayout;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.net.URL;

      import javax.swing.JButton;
      import javax.swing.JEditorPane;
      import javax.swing.JFrame;
      import javax.swing.JLabel;
      import javax.swing.ImageIcon;

      public class AnimTest extends JFrame {
      static final String IMAGE1 = "http://www.google.com/logos/google2.gif";
      static final String IMAGE2 = "http://www.google.com/logos/giroux3.gif";
      JButton labelButton;
      JButton paneButton;

      public AnimTest() {
      super("Testing Animated Icons");
      getContentPane().setLayout(new FlowLayout());
      // add animated label toggle button
      labelButton = new JButton("Toggle Label On");
      labelButton.addActionListener(new MyLabelListener());
      getContentPane().add(labelButton);
      // add animated label html pane toggle button
      paneButton = new JButton("Toggle Pane On");
      paneButton.addActionListener(new MyPaneListener());
      getContentPane().add(paneButton);
      // add thread dump button
      JButton threadButton = new JButton("Threads");
      threadButton.addActionListener(new ThreadListener());
      getContentPane().add(threadButton);
      }
      /** Add JLabel with text and animated icon. */
      protected class MyLabelListener extends MyToggleListener {
      protected void prepareComponent() {
      component = new JLabel("Label");
      try {
      ImageIcon icon = new ImageIcon(new URL(IMAGE1));
      ((JLabel)component).setIcon(icon);
      } catch (java.net.MalformedURLException _ex) {
      _ex.printStackTrace();
      }
      labelButton.setText("Toggle Label Off");
      }
      protected void destroyComponent() {
      ((JLabel)component).setIcon(null);
      labelButton.setText("Toggle Label On");
      }
      }
      /** Add JEditorPane with an img tag referencing an animated image. */
      protected class MyPaneListener extends MyToggleListener {
      protected void prepareComponent() {
      String src = IMAGE2;
      JEditorPane imagePane = new JEditorPane();
      imagePane.setContentType("text/html");
      imagePane.setEditable(false);
      imagePane.setText
      ("<html><body>Pane<img src=\"" + src
      + "\"></body></html>");
      component = imagePane;
      paneButton.setText("Toggle Pane Off");
      }
      protected void destroyComponent() {
      JEditorPane imagePane = (JEditorPane) component;
      imagePane.setDocument
      (imagePane.getEditorKit().createDefaultDocument
      ());
      imagePane.getEditorKit().deinstall(imagePane);
      paneButton.setText("Toggle Pane On");
      }
      }
      protected abstract class MyToggleListener implements ActionListener {
      boolean toggle = true;
      Component component = null;
      public void actionPerformed(ActionEvent ae) {
      if (toggle) {
      // create component
      prepareComponent();
      // add component
      getContentPane().add(component);
      toggle = false;
      } else {
      // clean up component
      destroyComponent();
      // remove component
      getContentPane().remove(component);
      component = null;
      toggle = true;
      }
      validate();
      repaint();
      }
      /** Create component. */
      protected abstract void prepareComponent();
      /** Clean up component. */
      protected abstract void destroyComponent();
      }
      protected class ThreadListener implements ActionListener {
      public void actionPerformed(ActionEvent ae) {
      System.out.println("\nAnimator Threads\n----------------
      ");
      Thread[] threads = new Thread[Thread.activeCount()+2];
      Thread.enumerate(threads);
      for (int x=0; x < threads.length; x++) {
      if (threads[x] != null &&
      threads[x].getName().indexOf
      ("Animator") > -1)
      {
      System.out.println(threads
      [x].getName());
      }
      }
      }
      }
      public static void main(String[] args) {
      AnimTest frame = new AnimTest();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(400, 200);
      frame.setLocation(200, 200);
      frame.show();
      }
      }

      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      Unknown. Overriding the imageUpdate in JEditorPane to
      return false when not visible does not work, since it isn't
      being called for animated GIF's referenced through HTML
      source in the pane. I don't know what class is being called.
      (Review ID: 180330)
      ======================================================================

            idk Igor Kushnirskiy (Inactive)
            jkimsunw Jeffrey Kim (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: