Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4425177
Votes 0
Synopsis GlyphView.java uses shorts instead of ints
Category java:classes_swing
Reported Against 1.3
Release Fixed
State 11-Closed, Will Not Fix, bug
Priority: 2-High
Related Bugs
Submit Date 13-MAR-2001
Description
Got the following error message from an application:

Exception occurred during event dispatching:
javax.swing.text.StateInvariantError: infinite loop in formatting
        at javax.swing.text.FlowView$FlowStrategy.layout(FlowView.java:429)
        at javax.swing.text.FlowView.layout(FlowView.java:182)
        at javax.swing.text.BoxView.setSize(BoxView.java:265)
        at javax.swing.text.BoxView.layout(BoxView.java:600)
        at javax.swing.text.BoxView.setSize(BoxView.java:265)
        at javax.swing.plaf.basic.BasicTextUI$RootView.paint(BasicTextUI.java:11
69)
        at javax.swing.plaf.basic.BasicTextUI.paintSafely(BasicTextUI.java:523)
        at javax.swing.plaf.basic.BasicTextUI.paint(BasicTextUI.java:657)
        at javax.swing.plaf.basic.BasicTextUI.update(BasicTextUI.java:636)
        at javax.swing.JComponent.paintComponent(JComponent.java:398)
        at javax.swing.JComponent.paint(JComponent.java:739)
        at javax.swing.JComponent.paintChildren(JComponent.java:523)
        at javax.swing.JComponent.paint(JComponent.java:748)
        at javax.swing.JComponent.paintChildren(JComponent.java:523)
        at javax.swing.JComponent.paint(JComponent.java:748)
        at javax.swing.JLayeredPane.paint(JLayeredPane.java:546)
        at javax.swing.JComponent.paintChildren(JComponent.java:523)
        at javax.swing.JComponent.paint(JComponent.java:719)
        at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:23)

        at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:
54)
        at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:91
)
        at java.awt.Container.paint(Container.java:960)
        at sun.awt.RepaintArea.paint(RepaintArea.java:298)
        at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:193)
        at java.awt.Component.dispatchEventImpl(Component.java:2665)
        at java.awt.Container.dispatchEventImpl(Container.java:1213)
        at java.awt.Window.dispatchEventImpl(Window.java:912)
        at java.awt.Component.dispatchEvent(Component.java:2499)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:319)
        at java.awt.EventDispatchThread.pumpOneEvent(EventDispatchThread.java:10
3)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:84)

Expected behavior: The text is shown

Actual behavior: Throws exception and text is never shown

Was it working before? If so, what was changed?

This is the first time that we tested it.

To Reproduce:

Run Bug with a value like 40000 - it happens *EVERY* time.  We've tried
values down to 33000 and it still happens.

It's caused by bugs in javax.swing.text.GlyphView.java - which uses a short
to represent the offset and length into a Document.  However if you set the
document with text that is 32767 or less characters the problem never occurs.

There is no workaround other than not setting text that long !!

Standalone Test Case:

 import javax.swing.*;
 
 public class Bug {
    /** Run with a number indicating the number of characters in the string **/
    public static void main(String aArgs[])
      throws Throwable {
      if (aArgs.length != 1) {
         System.err.println("Usage: Bug [No of characters]");
         System.exit(1);
       }
 
       int lLength = Integer.parseInt(aArgs[0]);
 
       JFrame lFrame = new JFrame("TestMe");
 
       JTextPane lText = new JTextPane();
       lText.setEditable(false);
       lText.setOpaque(false);
       lFrame.getContentPane().add(lText);
       lText.setText(getText(lLength));
       lFrame.setSize(500, 500);
       lFrame.setVisible(true);
    }
 
    private static String getText(int aLen) {
       StringBuffer lBuff = new StringBuffer();
       while (aLen > 6) {
          lBuff.append("12 21 ");
          aLen -= 6;
       }
       while (aLen > 0) {
          lBuff.append("a");
          aLen--;
       }
       return lBuff.toString();
    }
 }
Work Around
Add some linefeeds to keep paragraphs under Math.MAX_SHORT in length or 
provide your own GlyphView implementation from the ViewFactory.
Evaluation
This is intentional behavior.  It is a huge memory savings
to use shorts instead of ints since so many of these get created.
The limitation is that the longest GlyphView can be is
Math.MAX_SHORT characters at an offset of Math.MAX_SHORT
from Element.getStartOffset().   We feel this is a reasonable
restriction.  Element.getStartOffset is limited to Math.MAX_INT
so documents are not limited as claimed in the bug description.
The GlyphView restriction simply means a paragraph cannot exceed
Math.MAX_SHORT.  
 xxxxx@xxxxx  2001-03-13
Comments
  
  Include a link with my name & email   

Submitted On 03-JUL-2001
mort
Are you crazy?  It is *intentional* that it throws
exceptions?

If a webpage is loaded with a large paragraph, it is
*acceptable* that the page should fail to load and throw an
exception?


Submitted On 21-JAN-2002
holbrng
I am trying to use a TextPane to view log files, and get 
the same problem.. The file has about 260000 characters in 
it, and I don't believe it has any lines in it anywhere 
32767 characters.  All lines have \n linefeeds, and I blow 
up every time I load.  This NEEDS to be resolved.


Submitted On 19-JUN-2002
volkenborn
Well, thank you, pals!

This Error (note that it's not just an exception but an 
error) almost terminated a project we are trying to sell!

Try displaying a 60K sized, concatenated BASE64-encoded 
String with JEditorPane, and try to figure out why the 
application goes haywire!
If you would at least catch this error internally and throw 
a reasonable exception, I could see your point, but the way 
you approach this bug right now is plain ridiculous!

Even Lotus Notes didn't expect this behaviour and won't let 
you access mails with paragraphs this long... I too suggest 
you ought to rethink this issue.


Submitted On 30-SEP-2003
eliasen
I have filed another bug with Sun, including outlining the
workaround described here that requires no more memory.

Hopefully they won't close it and ignore customer input when
a win/win solution obviously exists.


Submitted On 30-SEP-2003
eliasen
Your customers don't feel that this is a reasonable
restriction, much less a reasonable implementation. The cast
to short blindly and silently loses data.  Code like this
should never be allowed in what is supposedly a
production-quality system.

This entire problem could be very easily resolved by simply
performing an architectural tweak: 

1. Make GlyphView an abstract class.

2. Make two (or more) subclasses of GlyphView; one that
stores offset and length as short (if memory savings are
that important) and one that stores them as int (so you can
actually do what your public interface indicates you can do,
and not lose data.)  Call them, say, GlyphViewShort and
GlyphViewInt.

3. Make createFragment(int p0, int p1) in GlyphView a
factory method that constructs the appropriate-sized
GlyphViewShort or GlyphViewInt depending on the size of p0
and p1.

4.  Instead of explicitly calling the GlyphView constructor,
create and call a factory method that constructs the
appropriately-sized GlyphView.

5.  Instead of accessing length and offset directly, access
them with a method int getLength() and int getOffset().

Thats it.  It's that easy.  It should take no more than 5
minutes to make all of your customers happy.

That's a lot better than telling your customers that their
code is unreasonable (even when you don't know what they
need to do,) and fail silently, or bomb out horribly if the
sign bits are wrong when you cast to short.


Submitted On 30-SEP-2003
eliasen
If you *really* want to save space for short paragraphs, you
can make a derived class GlyphViewByte that stores offset,
length, and that poorly-named variable "x" into bytes if
they're all small enough to fit.

I also noted in the other bug report that exceptions/errors
aren't thrown reliably--this can simply cause silent failure
too.


Submitted On 02-DEC-2003
eliasen
After I filed the bug on this, along with a solution on how
to fix it for real, Sun never responded.  Good job, guys.

If anyone at Sun can justify how a blind, narrowing cast to
short is a good idea in production code, please let us know. 

Again, I'll be happy to give you a much better solution
(that not only works in all cases, but saves *more* memory
than your bad bugfix here) as I outlined in the bug report I
filed.


Submitted On 08-MAY-2004
eliasen
To be fair, Sun did respond--almost seven months after I
filed the bug report.  They indicate that this bug was fixed
in JDK 1.5.0 beta, and it seems to be.  I'm doing Sun's job
for them and indicating that here, as they haven't.



PLEASE NOTE: JDK6 is formerly known as Project Mustang