【发布时间】:2014-01-30 11:57:56
【问题描述】:
一位用户报告说某个YouTube video 导致我们的程序失败。经过调查,似乎将包含该视频标题的字符串添加到 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;
}
}
每次 Swing 尝试渲染文本时,此堆栈跟踪都会打印到 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 报告吗?
【问题讨论】:
-
这可能是一个 JDK 错误。 Looking at the code 它似乎正在构建一个边界框,因此字体返回的其中一个字形可能不起作用(可能是一种坏字体,但 Swing 应该补偿)。为了缩小范围,我建议逐步从测试字符串中删除单个字符代码的所有实例(例如,删除所有
\u0D02,然后删除所有\u0D15等等......其中有 23 个)。跨度> -
另外,我会在
JTable中添加一个简单的 ASCII 列标签。没关系,但最好消除零长度字符串的可能性。 -
他们已经知道了。请参阅bugs.sun.com/bugdatabase/… 和bugs.sun.com/bugdatabase/view_bug.do?bug_id=5004101——据称已修复,但显然没有。错误报告可能会为您提供更多信息。
-
@kdgregory JDK-6374477 确实看起来非常相似,但它并没有修复。该报告来自 2006 年。:(
标签: java swing unicode crash fatal-error