-
Bug
-
Resolution: Fixed
-
P4
-
5.0
-
b18
-
x86
-
windows_xp
FULL PRODUCT VERSION :
java version "1.5.0_07"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-b03)
Java HotSpot(TM) Client VM (build 1.5.0_07-b03, mixed mode, sharing)
Also fails on 1.4.2_09
A DESCRIPTION OF THE PROBLEM :
AbstractAction contains an inner class ArrayTable, whose 'table' field is lazily instantiated, and nulled on clear(), and thus can be null. The clone() method assumes it is not null.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run provided code (see below). An uninitialized action (a1) clones happily. An action which has had a non-null value set (a2) also clones. An action which has had its values clear()ed or nulled fails to clone.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The output should be,
a1 cloned ok
a2 cloned ok
a3 cloned ok
ACTUAL -
The output is,
a1 cloned ok
a2 cloned ok
java.lang.NullPointerException
at javax.swing.ArrayTable.clone(ArrayTable.java:239)
at javax.swing.AbstractAction.clone(AbstractAction.java:248)
at AbstractActionBug.clone(AbstractActionBug.java:41)
at AbstractActionBug.main(AbstractActionBug.java:22)
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.NullPointerException
at javax.swing.ArrayTable.clone(ArrayTable.java:239)
at javax.swing.AbstractAction.clone(AbstractAction.java:248)
at AbstractActionBug.clone(AbstractActionBug.java:41)
at AbstractActionBug.main(AbstractActionBug.java:22)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
public final class AbstractActionBug extends AbstractAction implements Cloneable
{
public static final void main(String[] args)
{
try
{
AbstractActionBug a1 = new AbstractActionBug("a1");
a1 = (AbstractActionBug) a1.clone();
System.out.println("a1 cloned ok");
AbstractActionBug a2 = new AbstractActionBug("a2");
a2.putValue(NAME, "null");
a2 = (AbstractActionBug) a2.clone();
System.out.println("a2 cloned ok");
AbstractActionBug a3 = new AbstractActionBug(null);
a3 = (AbstractActionBug) a3.clone();
System.out.println("a3 cloned ok");
}
catch (Exception e)
{
e.printStackTrace();
}
}
private AbstractActionBug(String name)
{
putValue(NAME, name);
}
public Object clone()
{
AbstractActionBug clone;
try
{
clone = (AbstractActionBug) super.clone();
}
catch (CloneNotSupportedException e)
{
throw new InternalError();
}
return clone;
}
public void actionPerformed(ActionEvent e)
{
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Ensure all actions have at least one non-null value.
java version "1.5.0_07"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-b03)
Java HotSpot(TM) Client VM (build 1.5.0_07-b03, mixed mode, sharing)
Also fails on 1.4.2_09
A DESCRIPTION OF THE PROBLEM :
AbstractAction contains an inner class ArrayTable, whose 'table' field is lazily instantiated, and nulled on clear(), and thus can be null. The clone() method assumes it is not null.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run provided code (see below). An uninitialized action (a1) clones happily. An action which has had a non-null value set (a2) also clones. An action which has had its values clear()ed or nulled fails to clone.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The output should be,
a1 cloned ok
a2 cloned ok
a3 cloned ok
ACTUAL -
The output is,
a1 cloned ok
a2 cloned ok
java.lang.NullPointerException
at javax.swing.ArrayTable.clone(ArrayTable.java:239)
at javax.swing.AbstractAction.clone(AbstractAction.java:248)
at AbstractActionBug.clone(AbstractActionBug.java:41)
at AbstractActionBug.main(AbstractActionBug.java:22)
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.NullPointerException
at javax.swing.ArrayTable.clone(ArrayTable.java:239)
at javax.swing.AbstractAction.clone(AbstractAction.java:248)
at AbstractActionBug.clone(AbstractActionBug.java:41)
at AbstractActionBug.main(AbstractActionBug.java:22)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
public final class AbstractActionBug extends AbstractAction implements Cloneable
{
public static final void main(String[] args)
{
try
{
AbstractActionBug a1 = new AbstractActionBug("a1");
a1 = (AbstractActionBug) a1.clone();
System.out.println("a1 cloned ok");
AbstractActionBug a2 = new AbstractActionBug("a2");
a2.putValue(NAME, "null");
a2 = (AbstractActionBug) a2.clone();
System.out.println("a2 cloned ok");
AbstractActionBug a3 = new AbstractActionBug(null);
a3 = (AbstractActionBug) a3.clone();
System.out.println("a3 cloned ok");
}
catch (Exception e)
{
e.printStackTrace();
}
}
private AbstractActionBug(String name)
{
putValue(NAME, name);
}
public Object clone()
{
AbstractActionBug clone;
try
{
clone = (AbstractActionBug) super.clone();
}
catch (CloneNotSupportedException e)
{
throw new InternalError();
}
return clone;
}
public void actionPerformed(ActionEvent e)
{
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Ensure all actions have at least one non-null value.