<AWT Dev> StackOverflowError happened by TextField.setFont(...)

Ichiroh Takiguchi takiguc at linux.vnet.ibm.com
Fri Aug 24 08:12:11 UTC 2018


Hello.

I could see following exception by TextField.setFont(...) by jdk-12+6

=====================
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
         at 
java.desktop/javax.swing.plaf.basic.BasicTextUI$UpdateHandler.layoutContainer(BasicTextUI.java:2061)
         at java.desktop/java.awt.Container.layout(Container.java:1537)
         at java.desktop/java.awt.Container.doLayout(Container.java:1526)
         at 
java.desktop/java.awt.Container.validateTree(Container.java:1722)
         at java.desktop/java.awt.Container.validate(Container.java:1657)
         at 
java.desktop/sun.awt.X11.XTextFieldPeer.setFont(XTextFieldPeer.java:290)
         at java.desktop/java.awt.Component.validate(Component.java:2976)
         at 
java.desktop/java.awt.Container.validateTree(Container.java:1740)
         at java.desktop/java.awt.Container.validate(Container.java:1657)
         at 
java.desktop/sun.awt.X11.XTextFieldPeer.setFont(XTextFieldPeer.java:290)
         at java.desktop/java.awt.Component.validate(Component.java:2976)
         at 
java.desktop/java.awt.Container.validateTree(Container.java:1740)
...
=====================

It seemed that sun.awt.X11.XTextFieldPeer.setFont(...) was called 
recursively.

I used following test program to recreate this issue.
=====================
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.util.*;

public class FontChangeTest extends Frame
   implements ActionListener, ItemListener {
   Panel p;
   java.util.List list = Arrays.asList(
     "1","2","3","4","5","6","7","8","9");
   TextField[] textfs = new TextField[list.size()];;
   Choice fontName, fontStyle;
   TextField fontSize;
   final static String[] fontStyles = new String[]{
     "Plain","Bold","Italic","ItalicBold"};
   final static int[] fontStylesId = new int[]{
     Font.PLAIN,Font.BOLD,Font.ITALIC,Font.BOLD+Font.ITALIC};
   Button btn;
   final int fSize = 12;
   void shuffle() {
     Collections.shuffle(list);
     for(int i=0; i<list.size(); i++) {
       textfs[i].setText(list.get(i).toString());
     }
   }
   void init() {
     setLayout(new BorderLayout());
     Panel p0 = new Panel();
     p0.setLayout(new FlowLayout());
     add(p0, BorderLayout.NORTH);
     btn = new Button("Shuffle");
     btn.addActionListener(this);
     p0.add(btn);
     Panel p1 = new Panel();
     p1.setLayout(new FlowLayout());
     add(p1, BorderLayout.SOUTH);
     fontName = new Choice();
     fontName.addItemListener(this);
     for(String s : Toolkit.getDefaultToolkit().getFontList()) {
       fontName.add(s);
     }
     p1.add(fontName);
     fontStyle = new Choice();
     fontStyle.addItemListener(this);
     for(String s : fontStyles) {
       fontStyle.add(s);
     }
     p1.add(fontStyle);
     fontSize = new TextField(String.valueOf(fSize),2);
     fontSize.addActionListener(this);
     p1.add(fontSize);
     p = new Panel();
     add(p, BorderLayout.CENTER);
     p.setLayout(new GridLayout(0,3,3,3));
     for(int i=0; i<list.size(); i++) {
       textfs[i] = new TextField(1);
       textfs[i].setFont(new Font(fontName.getSelectedItem(),
                         fontStylesId[fontStyle.getSelectedIndex()],
                         fSize));
       p.add(textfs[i]);
     }
     shuffle();
   }
   public void changeFont() {
     int size;
     try {
       size = Integer.parseInt(fontSize.getText());
       for(int i=0; i<textfs.length; i++) {
         textfs[i].setFont(new Font(fontName.getSelectedItem(),
                           fontStylesId[fontStyle.getSelectedIndex()],
                           size));
       }
     } catch (java.lang.NumberFormatException nfe) {
     }
   }
   FontChangeTest() {
     super("FontChangeTest");
     init();
     addWindowListener(new WindowAdapter() {
       public void windowClosing(WindowEvent we) { System.exit(0); }
     });
     pack();
     setVisible(true);
   }
   public void actionPerformed(ActionEvent ae) {
     if (ae.getSource().equals(btn)) {
       p.setVisible(false);
       shuffle();
       p.setVisible(true);
     } else if (ae.getSource().equals(fontSize)) {
       changeFont();
       pack();
     }
   }
   public void itemStateChanged(ItemEvent ie) {
     changeFont();
     pack();
   }
   public static void main(String[] args) {
     new FontChangeTest();
   }
}
=====================

Test instruction is as follows:
1. Compile and run FontChangeTest
2. Press "Shuffle" button to top
3. Click left buttom's Choice button, then change "Dialog" to 
"SansSerif"
    Then above exception will be happened

It worked fine with JDK8
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

Failed by
openjdk version "12-ea" 2019-03-19
OpenJDK Runtime Environment 19.3 (build 12-ea+6)
OpenJDK 64-Bit Server VM 19.3 (build 12-ea+6, mixed mode)

One of fix candidate is:
=====================
diff -r 945ba9278a27 
src/java.desktop/share/classes/java/awt/Component.java
--- a/src/java.desktop/share/classes/java/awt/Component.java    Tue Aug 
07 00:06:52 2018 -0700
+++ b/src/java.desktop/share/classes/java/awt/Component.java    Fri Aug 
24 16:59:19 2018 +0900
@@ -1936,8 +1936,8 @@
              if (peer != null) {
                  f = getFont();
                  if (f != null) {
+                    peerFont = f;
                      peer.setFont(f);
-                    peerFont = f;
                  }
              }
          }
=====================

I'm not sure, it's good or not...

Thanks,
Ichiroh Takiguchi
IBM Japan, Ltd.



More information about the awt-dev mailing list