JDK-4951733 : LTP: Stack overflow encoding a derived Font with XMLEncoder
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.beans
  • Affected Version: 1.4.0,1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux,windows_xp
  • CPU: x86
  • Submitted: 2003-11-10
  • Updated: 2010-07-09
  • Resolved: 2011-03-08
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.
JDK 7
7 b07Fixed
Related Reports
Relates :  
Relates :  
Description
Name: jl125535			Date: 11/10/2003


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

FULL OS VERSION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
Encoding a font created using the deriveFont(float size) method from an existing font fails with a stack overflow exception. Encoding the original font or an apparently identical font created directly works. The problem seems to occur when the size of the derived font is not an integer.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached example. If the derived size (20.1f) is replaced with an integer value, the problem does not occur.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.2" class="java.beans.XMLDecoder">
 <object class="java.awt.Font">
  <string>dialog</string>
  <int>0</int>
  <int>20</int>
 </object>
</java>

ACTUAL -
See stack trace below.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.StackOverflowError
	at java.lang.Exception.<init>(Exception.java:77)
	at java.lang.reflect.InvocationTargetException.<init>(InvocationTargetException.java:54)
	at sun.reflect.GeneratedConstructorAccessor1.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:274)
	at java.beans.Statement.invoke(Statement.java:473)
	at java.beans.Expression.getValue(Expression.java:101)
	at java.beans.Encoder.getValue(Encoder.java:84)
	at java.beans.Encoder.get(Encoder.java:186)
	at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:97)

<The following lines of the stack trace repeat ad infinitum>
        at java.beans.Encoder.writeObject(Encoder.java:55)
        at java.beans.XMLEncoder.writeObject(XMLEncoder.java:250)
        at java.beans.Encoder.writeExpression(Encoder.java:260)
        at java.beans.XMLEncoder.writeExpression(XMLEncoder.java:363)
        at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:1
00)
etc

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.Font;
import java.beans.XMLEncoder;
import java.io.BufferedOutputStream;
import java.io.FileDescriptor;
import java.io.FileOutputStream;

public class TestXMLEncoder
{
	public static void main(String[] args)
	{
		Font f = new Font("dialog", 0, 20);
		f = f.deriveFont(20.1f);
		XMLEncoder encoder = 
            new XMLEncoder(new BufferedOutputStream(
			    new FileOutputStream(FileDescriptor.out)));
		encoder.writeObject(f);
		encoder.close();
	}
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Ensure fonts have integer sizes.
(Incident Review ID: 194149) 
======================================================================

Comments
EVALUATION New persistence delegate should be created to use Map attributes.
11-12-2006

SUGGESTED FIX We should add the following persistence delegate: final class java_awt_Font_PersistenceDelegate extends PersistenceDelegate { protected Expression instantiate(Object oldInstance, Encoder out) { Font font = (Font) oldInstance; Object[] args = new Object[] { font.getName(), font.getStyle(), font.getSize(), }; return new Expression(font, font.getClass(), "new", new Object[] {args}); } } -------------------------------------------------- Remove the following registartion, because it is not necessary: registerConstructor("java.awt.Font", new String[]{"name", "style", "size"});
19-04-2006

WORK AROUND Use whole numbers: 20.0f instead of 20.2f. ###@###.### 2003-11-11
11-11-2003

EVALUATION Using deriveFont() with fractional values causes this stack overflow. If whole numbers are used then the test works as expected. Exception in thread "main" java.lang.StackOverflowError at sun.reflect.GeneratedConstructorAccessor6.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:275) at java.beans.Statement.invoke(Statement.java:216) at java.beans.Expression.getValue(Expression.java:98) at java.beans.Encoder.getValue(Encoder.java:83) at java.beans.Encoder.get(Encoder.java:176) at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:94) at java.beans.Encoder.writeObject(Encoder.java:54) at java.beans.XMLEncoder.writeObject(XMLEncoder.java:254) at java.beans.Encoder.writeExpression(Encoder.java:255) at java.beans.XMLEncoder.writeExpression(XMLEncoder.java:366) at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:97) at java.beans.Encoder.writeObject(Encoder.java:54) at java.beans.XMLEncoder.writeObject(XMLEncoder.java:254) at java.beans.Encoder.writeExpression(Encoder.java:255) at java.beans.XMLEncoder.writeExpression(XMLEncoder.java:366) ... I think this is a result of a rounding error in which the float value for the size field is cast to an int. ###@###.### 2003-11-11
11-11-2003