-
Bug
-
Resolution: Cannot Reproduce
-
P3
-
None
-
1.4.2
-
x86
-
windows_2000
FULL PRODUCT VERSION :
java version "1.4.2_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_06-b03)
Java HotSpot(TM) Client VM (build 1.4.2_06-b03, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Win2K + SP4
EXTRA RELEVANT SYSTEM CONFIGURATION :
IE 6.0 + Java 1.4.2_06 plugin
A DESCRIPTION OF THE PROBLEM :
Applet's start() method, following the "new" Swing threading rules
espoused in Sun Bug # 5042754 constructs a simple GUI
entirely on the event dispatch thread. Yet, when the applet
attempts to insert text into a JTextArea from the event dispatch
thread, it deadlocks. The reason for the deadlock is that the
applet launching code in the sun.applet.AppletPanel,run() method
itself violates the "new" rule. While running NOT on the EDT,
the AppletPanel.run() does:
//...
case APPLET_START:
{
if (status != APPLET_INIT) {
showAppletStatus("notinited");
break;
}
applet.resize(currentAppletSize);
applet.start();
validate();
// Show the applet in event dispatch thread
// to avoid deadlock.
try
{
final Applet a = applet;
SwingUtilities.invokeAndWait(new Runnable()
//...
Since the thread running the validate() above is NOT the EDT,
the above code is violating the "new" rule. In fact, the above code
has been observed to be the cause of a deadlock in a real-world
applet that follows the "new" rule.
The example applet (in Test Case section) has some interlocking
wait/notify constructs added to ensure reproducibility of this bug
every time run. Without the wait/notify code in place, this bug has
been observed, but, being an MT bug, is difficult to reproduce.
Here are the stack traces from the two deadlocked threads:
Thread AWT-EventQueue-2 is holding the writeLock on the JTextArea's
document and attempting to acquire the AWT tree lock.
Thread [AWT-EventQueue-2] (Suspended)
TestApplet$3(java.awt.Component).invalidate() line: 2117
TestApplet$3(java.awt.Container).invalidate() line: 1038
TestApplet$3(javax.swing.JComponent).revalidate() line: 4389
javax.swing.plaf.basic.BasicTextUI$RootView.preferenceChanged(javax.swing.text.View, boolean, boolean) line: 1291
javax.swing.text.PlainView(javax.swing.text.View).preferenceChanged(javax.swing.text.View, boolean, boolean) line: 302
javax.swing.text.PlainView.updateDamage(javax.swing.event.DocumentEvent, java.awt.Shape, javax.swing.text.ViewFactory) line: 524
javax.swing.text.PlainView.insertUpdate(javax.swing.event.DocumentEvent, java.awt.Shape, javax.swing.text.ViewFactory) line: 421
javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(javax.swing.event.DocumentEvent, java.awt.Shape, javax.swing.text.ViewFactory) line: 1487
javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdate(javax.swing.event.DocumentEvent) line: 1726
TestApplet$2(javax.swing.text.AbstractDocument).fireInsertUpdate(javax.swing.event.DocumentEvent) line: 184
TestApplet$2.fireInsertUpdate(javax.swing.event.DocumentEvent) line: 100
TestApplet$2(javax.swing.text.AbstractDocument).handleInsertString(int, java.lang.String, javax.swing.text.AttributeSet) line: 749
TestApplet$2(javax.swing.text.AbstractDocument).insertString(int, java.lang.String, javax.swing.text.AttributeSet) line: 706
TestApplet$2(javax.swing.text.PlainDocument).insertString(int, java.lang.String, javax.swing.text.AttributeSet) line: 114
TestApplet$3(javax.swing.JTextArea).append(java.lang.String) line: 465
TestApplet$1.run() line: 60
java.awt.event.InvocationEvent.dispatch() line: 178
java.awt.EventQueue.dispatchEvent(java.awt.AWTEvent) line: 454
java.awt.EventDispatchThread.pumpOneEventForHierarchy(int, java.awt.Component) line: 201
java.awt.EventDispatchThread.pumpEventsForHierarchy(int, java.awt.Conditional, java.awt.Component) line: 151
java.awt.EventDispatchThread.pumpEvents(int, java.awt.Conditional) line: 145
java.awt.EventDispatchThread.pumpEvents(java.awt.Conditional) line: 137
java.awt.EventDispatchThread.run() line: 100
Thread applet-TestApplet.class is holding AWT tree lock
and attempting to acquire the readLock on the JTextArea's
document.
Thread [thread applet-TestApplet.class] (Suspended)
java.lang.Object.wait(long) line: not available [native method]
TestApplet$2(java.lang.Object).wait() line: 429
TestApplet$2(javax.swing.text.AbstractDocument).readLock() line: 1385
javax.swing.plaf.basic.BasicTextAreaUI(javax.swing.plaf.basic.BasicTextUI).getPreferredSize(javax.swing.JComponent) line: 797
TestApplet$3(javax.swing.JComponent).getPreferredSize() line: 1275
TestApplet$3(javax.swing.JTextArea).getPreferredSize() line: 612
TestApplet$3.getPreferredSize() line: 134
javax.swing.ScrollPaneLayout$UIResource(javax.swing.ScrollPaneLayout).layoutContainer(java.awt.Container) line: 769
javax.swing.JScrollPane(java.awt.Container).layout() line: 1020
javax.swing.JScrollPane(java.awt.Container).doLayout() line: 1010
javax.swing.JScrollPane(java.awt.Container).validateTree() line: 1092
javax.swing.JPanel(java.awt.Container).validateTree() line: 1099
javax.swing.JLayeredPane(java.awt.Container).validateTree() line: 1099
javax.swing.JRootPane(java.awt.Container).validateTree() line: 1099
TestApplet(java.awt.Container).validateTree() line: 1099
sun.plugin.AppletViewer(java.awt.Container).validateTree() line: 1099
sun.plugin.AppletViewer(java.awt.Container).validate() line: 1067
sun.plugin.AppletViewer(sun.applet.AppletPanel).run() line: 378
java.lang.Thread.run() line: 534
Threads AWT-EventQueue-2 and applet-TestApplet.class are deadlocked.
There is nothing the developer can do to resolve this issue. It's up to Sun to correct
the violation of the Swing thread rule (per Sun Bug # 5042754) in AppletPanel.run().
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) run the TestApplet
2) attach debugger and observe deadlocked threads
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The applet should not deadlock. Perhaps it should wait for an event that
will not occur (on one of the TestApplet's "lock" objects), but it should
not deadlock with one thread holding the document lock and waiting
for the AWT tree lock and the other thread holding the AWT tree lock and
waiting for the document lock.
ACTUAL -
Threads AWT-EventQueue-2 and applet-TestApplet.class are deadlocked.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
Here is the example applet that will deadlock every time run:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.text.PlainDocument;
/*
* Demonstrate AppletPanel bug.
* see: related bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5042754
* @author Terry Rosenbaum
* @version 1.0 Nov 14, 2004
*/
public class TestApplet extends JApplet
{
JTextArea itsTextArea;
Thread itsLauncherThread;
final Object itsWriteLockHeldLock = new Object();
boolean itsWriteLockHeld;
final Object itsTreeLockHeldLock = new Object();
boolean itsTreeLockHeld;
boolean itsGUIConstructionCompleted;
/**
* @throws java.awt.HeadlessException
*/
public TestApplet() throws HeadlessException
{
super();
}
public void init()
{
}
public void start()
{
SwingUtilities.invokeLater(
new Runnable()
{
public void run()
{
doStart();
}
}
);
}
public void doStart()
{
itsLauncherThread = Thread.currentThread();
constructGUI();
itsGUIConstructionCompleted = true;
final JTextArea aTextArea = itsTextArea;
// enqueue the text area update on the Swing event queue
SwingUtilities.invokeLater
(
new Runnable()
{
public void run()
{
aTextArea.append("This is some text\n");
}
}
);
}
void constructGUI()
{
PlainDocument aDocument = new PlainDocument()
{
protected void fireInsertUpdate(DocumentEvent e)
{
if(Thread.currentThread() != itsLauncherThread)
{
// looking at the code, we know write lock is held now
// notify other thread that we now hold the write lock
synchronized(itsWriteLockHeldLock)
{
itsWriteLockHeld = true;
itsWriteLockHeldLock.notify();
}
// wait until other thread notifies us that it holds the AWT tree lock
synchronized(itsTreeLockHeldLock)
{
while(!itsTreeLockHeld)
{
try
{
itsTreeLockHeldLock.wait();
}
catch(InterruptedException anException)
{
anException.printStackTrace();
}
}
}
// enter the deadlock
}
// continue with original Sun implementation
super.fireInsertUpdate(e);
}
};
itsTextArea = new JTextArea(aDocument, null, 6, 40)
{
public Dimension getPreferredSize()
{
if(itsGUIConstructionCompleted && Thread.currentThread() == itsLauncherThread)
{
// wait for the thread running the AWT event queue
// to notify us that it holds the write lock
synchronized(itsWriteLockHeldLock)
{
while(!itsWriteLockHeld)
{
try
{
itsWriteLockHeldLock.wait();
}
catch(InterruptedException anException)
{
anException.printStackTrace();
}
}
}
// notify the other thread that we hold the AWT tree lock
synchronized(itsTreeLockHeldLock)
{
itsTreeLockHeld = true;
itsTreeLockHeldLock.notify();
}
// enter the deadlock
}
return super.getPreferredSize();
};
};
itsTextArea.setMargin(new Insets(5,5,5,5));
itsTextArea.setEditable(false);
JPanel aPanel = new JPanel();
aPanel.setBackground(new Color(0xE1E5E8));
aPanel.setForeground(new Color(0xE1E5E8));
aPanel.setLayout(new BorderLayout());
JScrollPane aScrollPane = new JScrollPane(itsTextArea);
aScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
aScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
aPanel.add(aScrollPane, BorderLayout.CENTER);
aPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
setContentPane(aPanel);
}
}
---------- END SOURCE ----------
###@###.### 2004-11-15 23:41:59 GMT
java version "1.4.2_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_06-b03)
Java HotSpot(TM) Client VM (build 1.4.2_06-b03, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Win2K + SP4
EXTRA RELEVANT SYSTEM CONFIGURATION :
IE 6.0 + Java 1.4.2_06 plugin
A DESCRIPTION OF THE PROBLEM :
Applet's start() method, following the "new" Swing threading rules
espoused in Sun Bug # 5042754 constructs a simple GUI
entirely on the event dispatch thread. Yet, when the applet
attempts to insert text into a JTextArea from the event dispatch
thread, it deadlocks. The reason for the deadlock is that the
applet launching code in the sun.applet.AppletPanel,run() method
itself violates the "new" rule. While running NOT on the EDT,
the AppletPanel.run() does:
//...
case APPLET_START:
{
if (status != APPLET_INIT) {
showAppletStatus("notinited");
break;
}
applet.resize(currentAppletSize);
applet.start();
validate();
// Show the applet in event dispatch thread
// to avoid deadlock.
try
{
final Applet a = applet;
SwingUtilities.invokeAndWait(new Runnable()
//...
Since the thread running the validate() above is NOT the EDT,
the above code is violating the "new" rule. In fact, the above code
has been observed to be the cause of a deadlock in a real-world
applet that follows the "new" rule.
The example applet (in Test Case section) has some interlocking
wait/notify constructs added to ensure reproducibility of this bug
every time run. Without the wait/notify code in place, this bug has
been observed, but, being an MT bug, is difficult to reproduce.
Here are the stack traces from the two deadlocked threads:
Thread AWT-EventQueue-2 is holding the writeLock on the JTextArea's
document and attempting to acquire the AWT tree lock.
Thread [AWT-EventQueue-2] (Suspended)
TestApplet$3(java.awt.Component).invalidate() line: 2117
TestApplet$3(java.awt.Container).invalidate() line: 1038
TestApplet$3(javax.swing.JComponent).revalidate() line: 4389
javax.swing.plaf.basic.BasicTextUI$RootView.preferenceChanged(javax.swing.text.View, boolean, boolean) line: 1291
javax.swing.text.PlainView(javax.swing.text.View).preferenceChanged(javax.swing.text.View, boolean, boolean) line: 302
javax.swing.text.PlainView.updateDamage(javax.swing.event.DocumentEvent, java.awt.Shape, javax.swing.text.ViewFactory) line: 524
javax.swing.text.PlainView.insertUpdate(javax.swing.event.DocumentEvent, java.awt.Shape, javax.swing.text.ViewFactory) line: 421
javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(javax.swing.event.DocumentEvent, java.awt.Shape, javax.swing.text.ViewFactory) line: 1487
javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdate(javax.swing.event.DocumentEvent) line: 1726
TestApplet$2(javax.swing.text.AbstractDocument).fireInsertUpdate(javax.swing.event.DocumentEvent) line: 184
TestApplet$2.fireInsertUpdate(javax.swing.event.DocumentEvent) line: 100
TestApplet$2(javax.swing.text.AbstractDocument).handleInsertString(int, java.lang.String, javax.swing.text.AttributeSet) line: 749
TestApplet$2(javax.swing.text.AbstractDocument).insertString(int, java.lang.String, javax.swing.text.AttributeSet) line: 706
TestApplet$2(javax.swing.text.PlainDocument).insertString(int, java.lang.String, javax.swing.text.AttributeSet) line: 114
TestApplet$3(javax.swing.JTextArea).append(java.lang.String) line: 465
TestApplet$1.run() line: 60
java.awt.event.InvocationEvent.dispatch() line: 178
java.awt.EventQueue.dispatchEvent(java.awt.AWTEvent) line: 454
java.awt.EventDispatchThread.pumpOneEventForHierarchy(int, java.awt.Component) line: 201
java.awt.EventDispatchThread.pumpEventsForHierarchy(int, java.awt.Conditional, java.awt.Component) line: 151
java.awt.EventDispatchThread.pumpEvents(int, java.awt.Conditional) line: 145
java.awt.EventDispatchThread.pumpEvents(java.awt.Conditional) line: 137
java.awt.EventDispatchThread.run() line: 100
Thread applet-TestApplet.class is holding AWT tree lock
and attempting to acquire the readLock on the JTextArea's
document.
Thread [thread applet-TestApplet.class] (Suspended)
java.lang.Object.wait(long) line: not available [native method]
TestApplet$2(java.lang.Object).wait() line: 429
TestApplet$2(javax.swing.text.AbstractDocument).readLock() line: 1385
javax.swing.plaf.basic.BasicTextAreaUI(javax.swing.plaf.basic.BasicTextUI).getPreferredSize(javax.swing.JComponent) line: 797
TestApplet$3(javax.swing.JComponent).getPreferredSize() line: 1275
TestApplet$3(javax.swing.JTextArea).getPreferredSize() line: 612
TestApplet$3.getPreferredSize() line: 134
javax.swing.ScrollPaneLayout$UIResource(javax.swing.ScrollPaneLayout).layoutContainer(java.awt.Container) line: 769
javax.swing.JScrollPane(java.awt.Container).layout() line: 1020
javax.swing.JScrollPane(java.awt.Container).doLayout() line: 1010
javax.swing.JScrollPane(java.awt.Container).validateTree() line: 1092
javax.swing.JPanel(java.awt.Container).validateTree() line: 1099
javax.swing.JLayeredPane(java.awt.Container).validateTree() line: 1099
javax.swing.JRootPane(java.awt.Container).validateTree() line: 1099
TestApplet(java.awt.Container).validateTree() line: 1099
sun.plugin.AppletViewer(java.awt.Container).validateTree() line: 1099
sun.plugin.AppletViewer(java.awt.Container).validate() line: 1067
sun.plugin.AppletViewer(sun.applet.AppletPanel).run() line: 378
java.lang.Thread.run() line: 534
Threads AWT-EventQueue-2 and applet-TestApplet.class are deadlocked.
There is nothing the developer can do to resolve this issue. It's up to Sun to correct
the violation of the Swing thread rule (per Sun Bug # 5042754) in AppletPanel.run().
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) run the TestApplet
2) attach debugger and observe deadlocked threads
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The applet should not deadlock. Perhaps it should wait for an event that
will not occur (on one of the TestApplet's "lock" objects), but it should
not deadlock with one thread holding the document lock and waiting
for the AWT tree lock and the other thread holding the AWT tree lock and
waiting for the document lock.
ACTUAL -
Threads AWT-EventQueue-2 and applet-TestApplet.class are deadlocked.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
Here is the example applet that will deadlock every time run:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.text.PlainDocument;
/*
* Demonstrate AppletPanel bug.
* see: related bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5042754
* @author Terry Rosenbaum
* @version 1.0 Nov 14, 2004
*/
public class TestApplet extends JApplet
{
JTextArea itsTextArea;
Thread itsLauncherThread;
final Object itsWriteLockHeldLock = new Object();
boolean itsWriteLockHeld;
final Object itsTreeLockHeldLock = new Object();
boolean itsTreeLockHeld;
boolean itsGUIConstructionCompleted;
/**
* @throws java.awt.HeadlessException
*/
public TestApplet() throws HeadlessException
{
super();
}
public void init()
{
}
public void start()
{
SwingUtilities.invokeLater(
new Runnable()
{
public void run()
{
doStart();
}
}
);
}
public void doStart()
{
itsLauncherThread = Thread.currentThread();
constructGUI();
itsGUIConstructionCompleted = true;
final JTextArea aTextArea = itsTextArea;
// enqueue the text area update on the Swing event queue
SwingUtilities.invokeLater
(
new Runnable()
{
public void run()
{
aTextArea.append("This is some text\n");
}
}
);
}
void constructGUI()
{
PlainDocument aDocument = new PlainDocument()
{
protected void fireInsertUpdate(DocumentEvent e)
{
if(Thread.currentThread() != itsLauncherThread)
{
// looking at the code, we know write lock is held now
// notify other thread that we now hold the write lock
synchronized(itsWriteLockHeldLock)
{
itsWriteLockHeld = true;
itsWriteLockHeldLock.notify();
}
// wait until other thread notifies us that it holds the AWT tree lock
synchronized(itsTreeLockHeldLock)
{
while(!itsTreeLockHeld)
{
try
{
itsTreeLockHeldLock.wait();
}
catch(InterruptedException anException)
{
anException.printStackTrace();
}
}
}
// enter the deadlock
}
// continue with original Sun implementation
super.fireInsertUpdate(e);
}
};
itsTextArea = new JTextArea(aDocument, null, 6, 40)
{
public Dimension getPreferredSize()
{
if(itsGUIConstructionCompleted && Thread.currentThread() == itsLauncherThread)
{
// wait for the thread running the AWT event queue
// to notify us that it holds the write lock
synchronized(itsWriteLockHeldLock)
{
while(!itsWriteLockHeld)
{
try
{
itsWriteLockHeldLock.wait();
}
catch(InterruptedException anException)
{
anException.printStackTrace();
}
}
}
// notify the other thread that we hold the AWT tree lock
synchronized(itsTreeLockHeldLock)
{
itsTreeLockHeld = true;
itsTreeLockHeldLock.notify();
}
// enter the deadlock
}
return super.getPreferredSize();
};
};
itsTextArea.setMargin(new Insets(5,5,5,5));
itsTextArea.setEditable(false);
JPanel aPanel = new JPanel();
aPanel.setBackground(new Color(0xE1E5E8));
aPanel.setForeground(new Color(0xE1E5E8));
aPanel.setLayout(new BorderLayout());
JScrollPane aScrollPane = new JScrollPane(itsTextArea);
aScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
aScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
aPanel.add(aScrollPane, BorderLayout.CENTER);
aPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
setContentPane(aPanel);
}
}
---------- END SOURCE ----------
###@###.### 2004-11-15 23:41:59 GMT
- relates to
-
JDK-4853783 SwingSet2 as an applet deadlocks on startup on Solaris
-
- Resolved
-
-
JDK-5042754 Deadlock in JTextArea (really AbstractDocument) when initially showing the frame
-
- Closed
-