2014-01-11 11 views
5

あるYouTube videoが原因で、プログラムが異常終了することが報告されました。調査の結果、そのビデオのタイトルを含むStringをJTableに追加すると、レンダリングコードのどこかにArrayIndexOutOfBoundsExceptionが発生するようです。JREバグ? JTableには特定の文字列 - > ArrayIndexOutOfBoundsExceptionが含まれています

Windows XP、7および8、Ubuntu上のJava 7u45およびJava 8(b121)の両方でこれをテストして確認しました。ここで

は、問題を実証するテストプログラムです:

import javax.swing.*; 
import java.awt.*; 

public class TestJTableAIOOBE { 
    private static final String TEXT = "\u0D38\u0D4D\u0D31\u0D4D\u0D31\u0D40\u0D32\u0D4D\u200D \u0D15\u0D31\u0D3F\u0D15\u0D4D\u0D15\u0D24\u0D4D\u0D24\u0D3F\u0D2F\u0D3F\u0D32\u0D4D\u200D \u0D2F\u0D47\u0D36\u0D41\u0D15\u0D4D\u0D30\u0D3F\u0D38\u0D4D\u0D24\u0D41\u0D35\u0D3F\u0D28\u0D4D\u0D31\u0D46 \u0D30\u0D42\u0D2A\u0D02 \u0D2A\u0D4D\u0D30\u0D24\u0D4D\u0D2F\u0D15\u0D4D\u0D37\u0D2A\u0D4D\u0D2A\u0D46\u0D1F\u0D4D\u0D1F\u0D41"; 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       Font font = findFont(); 
       if (font == null) { 
        System.out.println("No suitable font found"); 
        return; 
       } 
       System.out.println("Using font: " + font); 
       JTable table = new JTable(new Object[][]{{TEXT}}, new Object[]{"title"}); 
       table.setFont(font); 
       JFrame frame = new JFrame(); 
       frame.add(table); 
       frame.pack(); 
       frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    private static Font findFont() { 
     GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
     for (Font font : ge.getAllFonts()) { 
      if (font.canDisplayUpTo(TEXT) == -1) { 
       return font.deriveFont(0, 12); 
      } 
     } 
     return null; 
    } 
} 

このスタックトレースは毎回スイングは、テキストをレンダリングしようとstderrに出力されます。

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 48 
    at sun.font.ExtendedTextSourceLabel.createCharinfo(ExtendedTextSourceLabel.java:814) 
    at sun.font.ExtendedTextSourceLabel.getCharinfo(ExtendedTextSourceLabel.java:548) 
    at sun.font.ExtendedTextSourceLabel.getLineBreakIndex(ExtendedTextSourceLabel.java:480) 
    at java.awt.font.TextMeasurer.calcLineBreak(TextMeasurer.java:330) 
    at java.awt.font.TextMeasurer.getLineBreakIndex(TextMeasurer.java:566) 
    at java.awt.font.LineBreakMeasurer.nextOffset(LineBreakMeasurer.java:359) 
    at java.awt.font.LineBreakMeasurer.nextOffset(LineBreakMeasurer.java:328) 
    at sun.swing.SwingUtilities2.clipString(SwingUtilities2.java:472) 
    at javax.swing.SwingUtilities.layoutCompoundLabelImpl(SwingUtilities.java:1023) 
    at javax.swing.SwingUtilities.layoutCompoundLabel(SwingUtilities.java:892) 
    at javax.swing.plaf.basic.BasicLabelUI.layoutCL(BasicLabelUI.java:94) 
    at javax.swing.plaf.basic.BasicLabelUI.layout(BasicLabelUI.java:201) 
    at javax.swing.plaf.basic.BasicLabelUI.paint(BasicLabelUI.java:164) 
    at javax.swing.plaf.ComponentUI.update(ComponentUI.java:161) 
    at javax.swing.JComponent.paintComponent(JComponent.java:777) 
    at javax.swing.JComponent.paint(JComponent.java:1053) 
    at javax.swing.CellRendererPane.paintComponent(CellRendererPane.java:151) 
    at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2115) 
    at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:2016) 
    at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1812) 
    at javax.swing.plaf.ComponentUI.update(ComponentUI.java:161) 
    at javax.swing.JComponent.paintComponent(JComponent.java:777) 
    at javax.swing.JComponent.paint(JComponent.java:1053) 
    at javax.swing.JComponent.paintChildren(JComponent.java:886) 
    at javax.swing.JComponent.paint(JComponent.java:1062) 
    at javax.swing.JComponent.paintChildren(JComponent.java:886) 
    at javax.swing.JComponent.paint(JComponent.java:1062) 
    at javax.swing.JLayeredPane.paint(JLayeredPane.java:586) 
    at javax.swing.JComponent.paintChildren(JComponent.java:886) 
    at javax.swing.JComponent.paintToOffscreen(JComponent.java:5224) 
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1532) 
    at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1455) 
    at javax.swing.RepaintManager.paint(RepaintManager.java:1252) 
    at javax.swing.JComponent.paint(JComponent.java:1039) 
    at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39) 
    at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79) 
    at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116) 
    at java.awt.Container.paint(Container.java:1973) 
    at java.awt.Window.paint(Window.java:3901) 
    at javax.swing.RepaintManager$3.run(RepaintManager.java:822) 
    at javax.swing.RepaintManager$3.run(RepaintManager.java:794) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:794) 
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769) 
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718) 
    at javax.swing.RepaintManager.access$1100(RepaintManager.java:62) 
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1680) 
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311) 
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744) 
    at java.awt.EventQueue.access$400(EventQueue.java:97) 
    at java.awt.EventQueue$3.run(EventQueue.java:697) 
    at java.awt.EventQueue$3.run(EventQueue.java:691) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:714) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) 

は、あなたはこれを再現することはできますか?文字列のどのような特異性が実際にこれを引き起こしますか?本当にJREバグですか?私はそれをOracleに報告すべきでしょうか?

+0

これはおそらくJDKのバグです。 [コードを見る](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/sun/font/ExtendedTextSourceLabel.java#ExtendedTextSourceLabel.createCharinfo%28%29 )それはバウンディングボックスを構築しているようで、おそらくフォントによって返されたグリフの1つが動作しません(おそらく悪いフォントですが、Swingはこれを補うべきです)。絞り込むには、テスト文字列から1文字コードのすべてのインスタンスを徐々に削除することをお勧めします(例えば、すべての\ u0D02を削除してから、\ u0D15をすべて削除するなど... 23個あります)。 – kdgregory

+0

また、単純なASCII列ラベルを 'JTable'に追加します。重要ではありませんが、長さゼロの文字列を可能性として排除することをお勧めします。 – kdgregory

+0

彼らはすでにそれについて知っています。 http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=8b833c54cb93d6c9cf416667dc02?bug_id=6374477およびhttp://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5004101-固定されていると思われますが、明らかにそうではありません。バグレポートはあなたにもっと詳しい情報を与えるかもしれません。 – kdgregory

答えて

2

バグは2014年1月にOracleに報告され、3ヵ月後に公開バグトラッカーにJDK-8041480と表示されました。このバグは、Java 9の2016年9月に修正されました。

1

Windows XP、7および8、UbuntuのJava 7u45およびJava 8(b121) の両方でこれをテストして確認しました。

JREのバグ?

  • だけではなく削除するには、これは

EDITは

JTableの

用(使用)フォントの問題です(文字列にヒント2times) \u200D - ZERO WIDTH JOINERを交換してください。生成された例外と

import javax.swing.*; 
import javax.swing.table.DefaultTableModel; 

public class Test { 

    private String TEXT = "Jesus appear in Knife \u0D38\u0D4D\u0D31\u0D4D\u0D31\u0D40" 
      + "\u0D32\u0D4D\u0D4D\u0D15\u0D31\u0D3F\u0D15\u0D4D\u0D15\u0D24\u0D4D\u0D24\u0D3F\u0D2F" 
      + "\u0D3F\u0D32\u0D4D\u0D15\u0D2F\u0D47\u0D36\u0D41\u0D15\u0D4D\u0D30\u0D3F\u0D38\u0D4D" 
      + "\u0D24\u0D41\u0D35\u0D3F\u0D28\u0D4D\u0D31\u0D46 \u0D30\u0D42\u0D2A\u0D02\u0D2A\u0D4D" 
      + "\u0D30\u0D24\u0D4D\u0D2F\u0D15\u0D4D\u0D37\u0D2A\u0D4D\u0D2A\u0D46\u0D1F\u0D4D\u0D1F\u0D41"; 
    private String _TEXT = "Jesus appear in Knife \u0D38\u0D4D\u0D31\u0D4D\u0D31\u0D40\u0D32\u0D4D\u200D " 
      + "\u0D15\u0D31\u0D3F\u0D15\u0D4D\u0D15\u0D24\u0D4D\u0D24\u0D3F\u0D2F\u0D3F\u0D32\u0D4D" 
      + "\u200D \u0D2F\u0D47\u0D36\u0D41\u0D15\u0D4D\u0D30\u0D3F\u0D38\u0D4D\u0D24\u0D41\u0D35" 
      + "\u0D3F\u0D28\u0D4D\u0D31\u0D46 \u0D30\u0D42\u0D2A\u0D02 \u0D2A\u0D4D\u0D30\u0D24\u0D4D" 
      + "\u0D2F\u0D15\u0D4D\u0D37\u0D2A\u0D4D\u0D2A\u0D46\u0D1F\u0D4D\u0D1F\u0D41"; 
    private JTable table; 
    DefaultTableModel model = new DefaultTableModel(
      new Object[][]{{_TEXT},}, 
      new String[]{"Col 1",}); 

    public Test() { 
     table.setFont(new java.awt.Font("Tahoma", 1, 21)); 
     table = new JTable(model); 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     frame.add(table); 
     frame.pack(); 
     frame.setVisible(true); 
    } 
    //http://stackoverflow.com/questions/21062484/jre-bug-jtable-contains-certain-string-arrayindexoutofboundsexception 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Test(); 
      } 
     }); 
    } 
} 

run: 
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
    at Bugs.Test.<init>(Test.java:28) 
    at Bugs.Test$1.run(Test.java:42) 
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251) 
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733) 
    at java.awt.EventQueue.access$200(EventQueue.java:103) 
    at java.awt.EventQueue$3.run(EventQueue.java:694) 
    at java.awt.EventQueue$3.run(EventQueue.java:692) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:703) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91) 
BUILD SUCCESSFUL (total time: 1 second) 
(これはシーケンスを文字無視するかなりの減少一部、多分私は、適切なフォント慣れていない)

EDIT_2他JComponentのが、レンダラの概念があります

enter image description here

import java.awt.*; 
import java.awt.event.*; 
import java.util.Locale; 
import javax.swing.*; 
import javax.swing.plaf.FontUIResource; 
import javax.swing.plaf.basic.BasicComboBoxRenderer; 
import javax.swing.table.DefaultTableModel; 

public class SystemFontDisplayer extends JFrame { 

    private static final long serialVersionUID = 1L; 
    private JFrame frame = new JFrame("Nimbus UIDeafaults and Font"); 
    private JComboBox fontsBox; 
    private javax.swing.Timer timer = null; 
    private String buggyConstalation = "Jesus appear in Knife \u0D38\u0D4D" 
      + "\u0D31\u0D4D\u0D31\u0D40\u0D32\u0D4D\u200D\u0D15\u0D31\u0D3F" 
      + "\u0D15\u0D4D\u0D15\u0D24\u0D4D\u0D24\u0D3F\u0D2F\u0D3F\u0D32" 
      + "\u0D4D\u200D \u0D2F\u0D47\u0D36\u0D41\u0D15\u0D4D\u0D30\u0D3F" 
      + "\u0D38\u0D4D\u0D24\u0D41\u0D35\u0D3F\u0D28\u0D4D\u0D31\u0D46" 
      + "\u0D30\u0D42\u0D2A\u0D02 \u0D2A\u0D4D\u0D30\u0D24\u0D4D\u0D2F" 
      + "\u0D15\u0D4D\u0D37\u0D2A\u0D4D\u0D2A\u0D46\u0D1F\u0D4D\u0D1F\u0D41"; 
    private JButton testButton = new JButton(buggyConstalation); 
    private JTextField testTextField = new JTextField(buggyConstalation); 
    private JLabel testLabel = new JLabel(buggyConstalation);//caused by \u200D 
    private JTable table; 
    private DefaultTableModel model; 

    public SystemFontDisplayer() { 
     GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
     String[] fontFamilyNames = ge.getAvailableFontFamilyNames(Locale.getDefault()); 
     fontsBox = new JComboBox(fontFamilyNames); 
     fontsBox.setSelectedItem("SansSerif"); 
     fontsBox.setRenderer(new ComboRenderer()); 
     fontsBox.addItemListener(new ItemListener() { 
      @Override 
      public void itemStateChanged(ItemEvent e) { 
       if (e.getStateChange() == ItemEvent.SELECTED) { 
        final String fontName = fontsBox.getSelectedItem().toString(); 
        fontsBox.setFont(new Font(fontName, Font.PLAIN, 16)); 
        start(); 
       } 
      } 
     }); 
     fontsBox.setSelectedItem(0); 
     fontsBox.getEditor().selectAll(); 
     model = new DefaultTableModel(
       new Object[][]{{buggyConstalation,buggyConstalation},}, 
       new String[]{"Col 1","Col 2",}); 
     table = new JTable(model);   
     frame.setLayout(new GridLayout(5, 0, 20, 20)); 
     frame.add(fontsBox); 
     frame.add(testButton); 
     frame.add(testTextField); 
     frame.add(testLabel); 
     frame.add(table); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLocation(200, 105); 
     frame.pack(); 
     java.awt.EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       fontsBox.setPopupVisible(true); 
       fontsBox.setPopupVisible(false); 
      } 
     }); 
     frame.setVisible(true); 
    } 

    private void start() { 
     timer = new javax.swing.Timer(750, updateCol()); 
     timer.setRepeats(false); 
     timer.start(); 
    } 

    public Action updateCol() { 
     return new AbstractAction("text load action") { 
      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       final Font fnt = new Font(fontsBox.getSelectedItem().toString(), Font.PLAIN, 12); 
       final FontUIResource res = new FontUIResource(fnt); 
       UIManager.getLookAndFeelDefaults().put("Button.font", res); 
       UIManager.getLookAndFeelDefaults().put("TextField.font", res); 
       UIManager.getLookAndFeelDefaults().put("Label.font", res); 
       UIManager.getLookAndFeelDefaults().put("Table.font", res); 
       SwingUtilities.updateComponentTreeUI(frame); 
      } 
     }; 
    } 

    public static void main(String arg[]) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       SystemFontDisplayer systemFontDisplayer = new SystemFontDisplayer(); 
      } 
     }); 
    } 

    private class ComboRenderer extends BasicComboBoxRenderer { 

     private static final long serialVersionUID = 1L; 

     @Override 
     public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 
      super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 
      final Object fntObj = value; 
      final String fontFamilyName = (String) fntObj; 
      setFont(new Font(fontFamilyName, Font.PLAIN, 16)); 
      return this; 
     } 
    } 
} 
0このコード例で使用されます
+0

''フォント ''の良い呼び出し::) –

+1

mKorbel、@AndrewThompson、 "Arial Unicode MS"フォントがコンピュータにインストールされているだけで例外はないことが明らかになりました* (*どのフォントがsetFont(...)を使って実際に設定されていても)。このフォントはMicrosoft Officeに付属しており、デフォルトでWindowsには含まれていません。 – ntoskrnl

+0

@ntoskrnl Huh。それは面白いですし、私は間違いなくその 'Font'がインストールされています(とMS Office)。 –

0

Malayalamのメニュー項目を表示するためにCode2000.ttfを使用すると、同様の問題が発生しました。

 

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 280 
    at sun.font.ExtendedTextSourceLabel.createCharinfo(ExtendedTextSourceLabel.java:814) 
    at sun.font.ExtendedTextSourceLabel.getCharinfo(ExtendedTextSourceLabel.java:548) 
    at sun.font.ExtendedTextSourceLabel.getCharX(ExtendedTextSourceLabel.java:357) 

最終的にメニュー項目名の末尾にスペースがあることがわかりました。これらの問題を解消してこの問題を解決しました。

..ede

関連する問題