JDK-8144703 : ClassCastException: sun.font.CompositeFont cannot be cast to PhysicalFont
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 8u66
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • Submitted: 2015-12-04
  • Updated: 2016-10-13
  • Resolved: 2016-06-29
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 8 JDK 9
8u112Fixed 9 b127Fixed
Related Reports
Relates :  
Description
Java app gives the following exception message:

Exception in thread "main" java.lang.ClassCastException: 
sun.font.CompositeFont cannot be cast to sun.font.PhysicalFont


Comments
There is no possibility to create an auto test since the problem is reproducible only with specific font file. As far as I understand we avoid creating manual regression tests.
10-06-2016

Problem description: If an incorrect font file is used, we unable to initialise the font during CompositeFont.doDeferredInitialisation() invocation and assign default physical font to the corresponding components entry. Later at the same method, (i.e. doDeferredInitialisation()) we try to update this entry one more time, since the name retrieved from the entry and the name provide by componentNames array are different. The method SunFontManager.findFont2D() may return a composite font for such case. As a result we get ClassCastException trying to assign CompositeFont object to the instance of PhysicalFont. Fix: Surround invocation of SunFontManager.findFont2D() inside CompositeFont.doDeferredInitialisation() with 'try-catch' to avoid propagation of ClassCastException.
09-06-2016

It seems the font file provided by the submitter has an incorrect format or something like that. Windows font viewer cannot open Helvetica.ttf and reports that it is not a valid font file. Java is unable to retrieve 'font name' and 'family name' during initialisation which take place at CompositeFont.doDeferredInitialisation() and assigns default physical font (Lucida Sans Regular) to the corresponding components entry. Later at the same method, (i.e. doDeferredInitialisation()) we try to update this entry one more time, since the name retrieved from the entry and the name provide by componentNames array are different. The method SunFontManager.findFont2D() returns a composite font for the name 'Helvetica', since this font is only present as a part of composite. As a result we get ClassCastException trying to assign CompositeFont object to the instance of PhysicalFont. So the exception is caused by incorrect font file format. Note: I converted provided font file (Helvetica.ttf) to TrueTypeFont using on-line font converter at http://www.files-conversion.com/font-converter.php I was not able to reproduce the problem using the converted font file. Anyway I think we should NOT fail with ClassCastException even if a font file with incorrect format is used.
09-06-2016

The problem is reproducible on jdk8u92 and jdk9
09-06-2016

The fix for JDK-8132850 didn't resolve the problem. It just changed the conditions under which the issue can be observed. ClassCastException is still reproducible on Linux with a slightly changed test case (CanDisplayTest2.java). The steps to reproduce are the same.
09-06-2016

The problem is reproducible on Linux. Steps to reproduce: 1. Install font, (i.e. 'cp Helvetica.ttf /usr/share/fonts' and then 'sudo fc-cache -f') 2. Run the test, (i.e. 'java CanDisplayTest') Actual results: The following exception is thrown Exception in thread "main" java.lang.ClassCastException: sun.font.CompositeFont cannot be cast to sun.font.PhysicalFont at sun.font.CompositeFont.doDeferredInitialisation(CompositeFont.java:274) at sun.font.CompositeFont.getSlotFont(CompositeFont.java:341) at sun.font.CompositeGlyphMapper.getSlotMapper(CompositeGlyphMapper.java:114) at sun.font.CompositeGlyphMapper.convertToGlyph(CompositeGlyphMapper.java:124) at sun.font.CompositeGlyphMapper.charToGlyph(CompositeGlyphMapper.java:182) at sun.font.CharToGlyphMapper.canDisplay(CharToGlyphMapper.java:55) at sun.font.CompositeFont.canDisplay(CompositeFont.java:424) at java.awt.Font.canDisplay(Font.java:1977) at CanDisplayTest2.main(CanDisplayTest2.java:5) Expected results: The test should print out 'false'.
09-06-2016

Tests and font file attached
09-06-2016

Most likely the problem is already fixed by JDK-8132850
27-04-2016