JDK-4688560 : 1.4.0 REGRESSION: DefaultCaret calls back into View hierachy du
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2002-05-21
  • Updated: 2003-09-26
  • Resolved: 2003-09-26
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 tigerFixed
Related Reports
Relates :  
Relates :  
Description

Name: rmT116609			Date: 05/21/2002


FULL PRODUCT VERSION :
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)

FULL OPERATING SYSTEM VERSION :

Linux simia 2.2.19 #20 Tue May 15 20:53:22 CEST 2001 i686 unknown libc-2.1.3-141
& Windows 2000

A DESCRIPTION OF THE PROBLEM :
When adjusting dot/mark after a DocumentEvent, DefaultCaret calls directly into the view hierarchy (addHighlight etc. see stack trace). It should not do so because the hierarchy may be in an unstable state if it has not handled the event yet (i.e the caret's event listener is executed before the BasicTextUI's which then informs the Views). Instead, it should defer (SwingUtilities.invokeLater) this until the Views have adjusted to the Document change.

This bug only seems to occur in 1.4, but I don't see why it worked in 1.3 (the relevant code doesn't seem to have been changed), so maybe it is only harder to produce it.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the code.


EXPECTED VERSUS ACTUAL BEHAVIOR :
No exception  (obviously)
Exception (and sometimes an infinite loop).


ERROR MESSAGES/STACK TRACES THAT OCCUR :
javax.swing.text.StateInvariantError: infinite loop in formatting
        at javax.swing.text.FlowView$FlowStrategy.layout(FlowView.java:403)
        at javax.swing.text.FlowView.layout(FlowView.java:182)
        at javax.swing.text.BoxView.setSize(BoxView.java:379)
        at javax.swing.text.BoxView.updateChildSizes(BoxView.java:348)
        at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:330)
        at javax.swing.text.BoxView.layout(BoxView.java:682)
        at javax.swing.text.BoxView.setSize(BoxView.java:379)
        at javax.swing.text.BoxView.updateChildSizes(BoxView.java:343)
        at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:316)
        at javax.swing.text.BoxView.layout(BoxView.java:682)
        at javax.swing.text.BoxView.setSize(BoxView.java:379)
        at javax.swing.text.BoxView.updateChildSizes(BoxView.java:348)
        at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:330)
        at javax.swing.text.BoxView.layout(BoxView.java:682)
        at javax.swing.text.BoxView.setSize(BoxView.java:379)
        at javax.swing.text.BoxView.updateChildSizes(BoxView.java:348)
        at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:330)
        at javax.swing.text.BoxView.layout(BoxView.java:682)
        at javax.swing.text.BoxView.setSize(BoxView.java:379)
        at javax.swing.text.BoxView.updateChildSizes(BoxView.java:348)
        at javax.swing.text.BoxView.setSpanOnAxis(BoxView.java:330)
        at javax.swing.text.BoxView.layout(BoxView.java:682)
        at javax.swing.text.BoxView.setSize(BoxView.java:379)
        at
javax.swing.plaf.basic.BasicTextUI$RootView.setSize(BasicTextUI.java:15
28)
        at javax.swing.plaf.basic.BasicTextUI.damageRange(BasicTextUI.java:998)
        at javax.swing.plaf.basic.BasicTextUI.damageRange(BasicTextUI.java:979)
        at
javax.swing.text.DefaultHighlighter.addHighlight(DefaultHighlighter.jav
a:107)
        at javax.swing.text.DefaultCaret.handleMoveDot(DefaultCaret.java:878)
        at javax.swing.text.DefaultCaret.moveDot(DefaultCaret.java:851)
        at
javax.swing.text.DefaultCaret$UpdateHandler.removeUpdate(DefaultCaret.j
ava:1515)
        at
javax.swing.text.AbstractDocument.fireRemoveUpdate(AbstractDocument.jav
a:242)
        at
javax.swing.text.AbstractDocument.handleRemove(AbstractDocument.java:61
1)
        at javax.swing.text.AbstractDocument.remove(AbstractDocument.java:575)
        at CaretBug$1.actionPerformed(CaretBug.java:39)
        at javax.swing.Timer.fireActionPerformed(Timer.java:271)
        at javax.swing.Timer$DoPostEvent.run(Timer.java:201)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:178)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:443)
        at
java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThre
ad.java:190)
        at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread
.java:144)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:130)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:98)

This bug can be reproduced always.

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

import java.io.*;

public class CaretBug
{
    public static void main(String[] args)
        throws Exception
    {
        HTMLEditorKit k = new HTMLEditorKit();
	
        final HTMLDocument d = new HTMLDocument();

        k.read(new StringReader("<html><table><td><p>ABC<td><p>DEF"), d, 0);

	final	JEditorPane pane = new JEditorPane();
	
	pane.setEditorKit(k);
	pane.setDocument(d);

	pane.setCaret(new DefaultCaret());

	JFrame f = new JFrame();

	f.getContentPane().add(new JScrollPane(pane));

	Timer t = new Timer(3000, new ActionListener()
        {
	    public void actionPerformed(ActionEvent e)
	    {
		try
		{
		    pane.select(3, 6);
		    d.remove(5, 1);
		    d.remove(3, 1);
		}
		catch (Exception x)
		{
		    x.printStackTrace();
		}
	    }
        });

        t.setRepeats(false);
	t.start();

	f.pack(); f.show();
    }
}
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Call updateUI() after setDocument() so that hopefully the UIs DocumentListener is executed before the Caret's.

Release Regression From : 1.3.1_03
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.

(Review ID: 146200) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger FIXED IN: tiger INTEGRATED IN: tiger tiger-b22
2004-06-14

EVALUATION Name: ik75403 Date: 11/11/2002 This bug will not be fixed in 1.4.2 ====================================================================== Name: anR10225 Date: 08/27/2003 The problem appears when DefaultCaret is notified on document changes _before_ TextUI. Caret tries to update its selection and calls TextUI.damageRange() on out-of-date View hierarchy. DefaultHighlighter should put all damadeRange() calls to the event queue (invokeLater()) to make them safe. ====================================================================== Name: anR10225 Date: 09/01/2003 The test case supplied doesn't reproduce the bug since jdk build 1.5.0b12 (the bug #4623342 was fixed there) The following test case reproduces the bug in the latest builds: public class bug4688560 extends JFrame { public static void main(String[] args) throws Exception { final JEditorPane pane = new JEditorPane("text/html", "ABC<b>n</b>DEF"); final HTMLDocument d = (HTMLDocument) pane.getDocument(); Element e = d.getCharacterElement(3); d.setCharacterAttributes(4,1, e.getAttributes(), true); pane.setCaret(new DefaultCaret()); final JFrame f = new JFrame(); f.getContentPane().add(new JScrollPane(pane)); f.pack(); f.show(); Util.blockTillDisplayed(f); Thread.sleep(2000); SwingUtilities.invokeAndWait( new Runnable() { public void run() { pane.select(2, 7); try { d.remove(5, 1); d.remove(3, 1); } catch(BadLocationException e) { e.printStackTrace(); } } }); } } ======================================================================
2004-06-11