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

JTextArea (inside JScrollPane) rendering slows down (blocks EDT) with specific characters

XMLWordPrintable

      FULL PRODUCT VERSION :
      java version "1.8.0_131"
      Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
      Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 10.0.10586]


      A DESCRIPTION OF THE PROBLEM :
      With specific (strange) characters, the rendering of text blocks the EDT for a few seconds up to minutes, then works again.
      The blocking occurs after calling textArea.setText() or AbstractDocument.insertString().

      The specific characters originate from an EBCDIC-encoded file that was read using UTF-8 (I'm aware that's incorrect).
      Profiling the app showed that in such a case, a huge amount of char arrays (gigabytes in my app) was created in javax.swing.text.GapContent.getChars(int, int, Segment). Apparently, the code path commented with "// partial return not allowed, must copy" was entered in such a case.

      I attached a program that reproduces the problem.
      There's a noticeable lag when including a specific string, when not, rendering is instant.
      Why I do this? I ran across this on coincidence when writing an app that views several files at once, and the IBM500-encoded zos/jawt_md.h file was included. Everything was read UTF-8.
      I'm aware that reading EBCDIC with UTF-8 is wrong, but I still think that those ugly chars should not cause the EDT to block.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Please run the sample program

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      EDT should not block on specific characters
      ACTUAL -
      EDT blocks, app does not respond at all, for seconds/minutes.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.*;
      import javax.swing.*;
      import javax.swing.text.*;

      public class FooFrame {

      static String s0 = "Hello World";
      // (truncated) contents of jdk-headers-1.6.0/include/ibm/zos/jawt_md.h file encoding=IBM500/EBCDIC, read with UTF8
      static String s1 = "a\\\u0015@\\@~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u0015@\\@@\ufffd\ufffd\ufffd@\u00d6\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0015@\\@@\ufffd\ufffd\ufffd@\u25a4\ufffd\ufffd\ufffd@\u0501\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0015@\\\u0015@\\@@\ufffd\ufffd\ufffd@\ufffd\ufffd\ufffdk@\u0441\ufffd\ufffdM\ufffd\ufffd]@\u3143\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd@\u0144\ufffd\ufffd\ufffd\ufffd\ufffdk@\ufffd\ufffd\u0015@\\@@M\ufffd]@\u00d6\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd@\ufffd\ufffd\ufffd@\u00d6\ufffd\ufffdK@\ufffd\ufffd\ufffd\ufffdk@\ufffd\ufffd\ufffd\ufffdK@\ufffd\ufffd\ufffd@\u0649\ufffd\ufffd\ufffd\ufffd@\u0645\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u0015@\\\u0015@\\";

      public static void main(String[] args) throws Exception {
      EventQueue.invokeAndWait(() -> new FooFrame().go());
      }

      void go() {
      JFrame frame = new JFrame("BugRepro");
      frame.setBounds(100, 100, 800, 600);
      frame.setContentPane(foo());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
      }

      JCheckBox c;

      JPanel foo() {
      JPanel panel = new JPanel(new BorderLayout());
      JButton b;
      JTextArea area = new JTextArea();
      JPanel p = new JPanel(new FlowLayout());
      panel.add(p, BorderLayout.NORTH);
      p.add(b = new JButton("click me"));
      p.add(c = new JCheckBox("include strange chars", true));
      panel.add(new JLabel("Hello"), BorderLayout.SOUTH);
      panel.add(new JScrollPane(area), BorderLayout.CENTER);

      // need to set a new Document b/c setText() sets the text of the old document.
      b.addActionListener(e -> area.setDocument(makeDoc()));
      return panel;
      }

      Document makeDoc() {
      Document doc = new PlainDocument();
      try {
      doc.insertString(0, makeString(), new SimpleAttributeSet());
      } catch (BadLocationException e) {
      throw new Error(e);
      }
      return doc;
      }

      String makeString() {
      int MAX = 1000;

      StringBuilder buf = new StringBuilder();
      extracted(MAX, buf);
      System.out.println("Including strange chars: " + c.isSelected());
      if (c.isSelected()) {
      buf.append(s1); // XXX This line slows down the rendering noticeably since it contains strange chars
      }
      extracted(MAX, buf);

      return buf.toString();
      }

      static void extracted(int MAX, StringBuilder buf) {
      for (int i = 0; i < MAX; i++) {
      buf.append(s0);
      buf.append("\n");
      }
      }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      Not passing those chars into a text component.

            psadhukhan Prasanta Sadhukhan
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: