-
Bug
-
Resolution: Fixed
-
P5
-
5.0
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2166606 | 6u11 | Igor Nekrestyanov | P3 | Resolved | Fixed | b01 |
JDK-2166640 | 6u8 | Igor Nekrestyanov | P2 | Resolved | Fixed | b02 |
JDK-2166732 | 5.0u17 | Mala Bankal | P2 | Resolved | Fixed | b02 |
FULL PRODUCT VERSION :
java version "1.5.0_05"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_05-b05)
Java HotSpot(TM) Client VM (build 1.5.0_05-b05, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Linux 2.4.21-37.ELsmp #1 SMP Wed Sep 7 13:28:55 EDT 2005 i686 i686 i386 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
Our java server (using intensively font files) was freezing almost every day reporting from time to time the recursive following stack trace in the log file :
2005-11-16 11:51:23,700 ERROR [STDERR] java.awt.FontFormatException: java.lang.NullPointerException
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.TrueTypeFont.open(TrueTypeFont.java:251)
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.TrueTypeFont.readBlock(TrueTypeFont.java:279)
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.FileFont.getGlyphAdvance(Native Method)
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.FileFontStrike.getGlyphAdvance(FileFontStrike.java:491)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FileFontStrike.getCodePointAdvance(FileFontStrike.java:502)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FontDesignMetrics.handleCharWidth(FontDesignMetrics.java:226)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FontDesignMetrics.getLatinCharWidth(FontDesignMetrics.java:235)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FontDesignMetrics.stringWidth(FontDesignMetrics.java:285)
2005-11-16 11:51:23,701 ERROR [STDERR] at com.sun.java.swing.SwingUtilities2.stringWidth(SwingUtilities2.java:292)
2005-11-16 11:51:23,701 ERROR [STDERR] at javax.swing.SwingUtilities.computeStringWidth(SwingUtilities.java:761)
...
We couldn't reproduce this behaviour on our test server until we tried this simple test : start the server and run a scenario using font files, then delete the .tmp file generated in the jvm temp directory.
Apparently, this leads to the error we had on the production server. For some reason, the tmp directory is cleaned up by some daemon. Though we still have to investigate about this linux daemon which should not run, the error generated in the jvm can not be recovered and finally freezes the server which should not normally happen.
Indeed, the open or readBlock method is synchronized and any other thread trying to use font files even if the tmp file still exists is stuck by the one that tries indefinitely to write error logs because of the NullPointerException.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Start the server and run a scenario using font files, then delete the .tmp file generated in the jvm temp directory.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
If the font tmp file was deleted : throw an exception catchable by the calling thread.
ACTUAL -
Recursive stack traces in the log file + blocked threads + finally server freeze.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
:
2005-11-16 11:51:23,700 ERROR [STDERR] java.awt.FontFormatException: java.lang.NullPointerException
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.TrueTypeFont.open(TrueTypeFont.java:251)
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.TrueTypeFont.readBlock(TrueTypeFont.java:279)
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.FileFont.getGlyphAdvance(Native Method)
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.FileFontStrike.getGlyphAdvance(FileFontStrike.java:491)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FileFontStrike.getCodePointAdvance(FileFontStrike.java:502)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FontDesignMetrics.handleCharWidth(FontDesignMetrics.java:226)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FontDesignMetrics.getLatinCharWidth(FontDesignMetrics.java:235)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FontDesignMetrics.stringWidth(FontDesignMetrics.java:285)
2005-11-16 11:51:23,701 ERROR [STDERR] at com.sun.java.swing.SwingUtilities2.stringWidth(SwingUtilities2.java:292)
2005-11-16 11:51:23,701 ERROR [STDERR] at javax.swing.SwingUtilities.computeStringWidth(SwingUtilities.java:761)
...
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
Using this fonction in loop on several fonts and images while deleting the tmp font files in the jvm tmp dir :
private static boolean checkWidth(String text, Font font, Graphics graphics, int imgWidth) {
final FontMetrics fm = graphics.getFontMetrics(font);
final int width = SwingUtilities.computeStringWidth(fm, text);
return imgWidth > width;
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Using our own java.io.tmpdir directory and cleaning up the tmp files manually when the corresponding font file is not used any more solved the problem.
Here is a piece of code that produces the exception.
You need to place a directory called 'font' with more than 20 ttf fonts in
it (so at least 21) at the same level you compile and run this code (i don't
know if our fonts are special but I guess you can reproduce the problem with
any font files).
Compile and just run the test :
java -cp . CheckFontWidth
/*
* Copyright 2004 Mediabilis S.A.S., 135 rue de Billancourt,
* 92514 Boulogne-Billancourt, France
* www.mediabilis.com, ###@###.###
* All Rights Reserved.
*
* Created on 29 oct. 2004
*/
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.swing.SwingUtilities;
/**
*
* @version 1.0 29 oct. 2004
* @author j.guyard
*/
public class CheckFontWidth {
// Font cache map
private static Map fonts;
public static void main(String[] args) {
try {
// Init font cache
fonts = new HashMap();
// list font file names
File fontdir = new File("font");
String[] fontStrs = fontdir.list();
System.out.println("Nb of fonts = " + fontStrs.length);
Font font = null;
int i = 0;
BufferedImage img = new
BufferedImage(10,10,BufferedImage.TYPE_INT_RGB);
while (true)
{
System.out.println("i = " + i);
// get and cache next font
font = getFont("font/" + fontStrs[i++]);
// Use a text that changes (hour for instance)
String text = String.valueOf(System.currentTimeMillis());
// Compute width
int width =
SwingUtilities.computeStringWidth(img.createGraphics().getFontMetrics(font),
text);
// Reset counter and delete tmp file
if (i == (fontStrs.length)) {
System.out.println("Reset counter and delete tmp
file.");
i = 0;
File tmp = new
File(System.getProperties().getProperty("java.io.tmpdir"));
if (tmp.exists()) {
File[] tmpFiles = tmp.listFiles(new
FilenameFilter(){
public boolean accept(File file, String str) {
final String [] ext = str.split("[.]");
if (ext.length >= 2) {
return ext[ext.length-1].equals("tmp");
} else {
return false;
}
}
});
for (int j = 0; j < tmpFiles.length; j++) {
File file = tmpFiles[j];
file.delete();
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (FontFormatException e) {
e.printStackTrace();
}
}
// Font loading method
public static Font getFont(String path) throws IOException,
FontFormatException {
final File fontFile = new File(path);
final Font font;
if (!fonts.containsKey(path)) {
InputStream fontStream = null;
try {
fontStream = new FileInputStream(path);
font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
} finally {
if (null != fontStream) {
try {
fontStream.close();
} catch (IOException ioe) {
}
}
}
fonts.put(path, font);
} else {
font = (Font) fonts.get(path);
}
return font;
}
}
java version "1.5.0_05"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_05-b05)
Java HotSpot(TM) Client VM (build 1.5.0_05-b05, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Linux 2.4.21-37.ELsmp #1 SMP Wed Sep 7 13:28:55 EDT 2005 i686 i686 i386 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
Our java server (using intensively font files) was freezing almost every day reporting from time to time the recursive following stack trace in the log file :
2005-11-16 11:51:23,700 ERROR [STDERR] java.awt.FontFormatException: java.lang.NullPointerException
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.TrueTypeFont.open(TrueTypeFont.java:251)
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.TrueTypeFont.readBlock(TrueTypeFont.java:279)
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.FileFont.getGlyphAdvance(Native Method)
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.FileFontStrike.getGlyphAdvance(FileFontStrike.java:491)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FileFontStrike.getCodePointAdvance(FileFontStrike.java:502)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FontDesignMetrics.handleCharWidth(FontDesignMetrics.java:226)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FontDesignMetrics.getLatinCharWidth(FontDesignMetrics.java:235)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FontDesignMetrics.stringWidth(FontDesignMetrics.java:285)
2005-11-16 11:51:23,701 ERROR [STDERR] at com.sun.java.swing.SwingUtilities2.stringWidth(SwingUtilities2.java:292)
2005-11-16 11:51:23,701 ERROR [STDERR] at javax.swing.SwingUtilities.computeStringWidth(SwingUtilities.java:761)
...
We couldn't reproduce this behaviour on our test server until we tried this simple test : start the server and run a scenario using font files, then delete the .tmp file generated in the jvm temp directory.
Apparently, this leads to the error we had on the production server. For some reason, the tmp directory is cleaned up by some daemon. Though we still have to investigate about this linux daemon which should not run, the error generated in the jvm can not be recovered and finally freezes the server which should not normally happen.
Indeed, the open or readBlock method is synchronized and any other thread trying to use font files even if the tmp file still exists is stuck by the one that tries indefinitely to write error logs because of the NullPointerException.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Start the server and run a scenario using font files, then delete the .tmp file generated in the jvm temp directory.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
If the font tmp file was deleted : throw an exception catchable by the calling thread.
ACTUAL -
Recursive stack traces in the log file + blocked threads + finally server freeze.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
:
2005-11-16 11:51:23,700 ERROR [STDERR] java.awt.FontFormatException: java.lang.NullPointerException
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.TrueTypeFont.open(TrueTypeFont.java:251)
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.TrueTypeFont.readBlock(TrueTypeFont.java:279)
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.FileFont.getGlyphAdvance(Native Method)
2005-11-16 11:51:23,700 ERROR [STDERR] at sun.font.FileFontStrike.getGlyphAdvance(FileFontStrike.java:491)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FileFontStrike.getCodePointAdvance(FileFontStrike.java:502)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FontDesignMetrics.handleCharWidth(FontDesignMetrics.java:226)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FontDesignMetrics.getLatinCharWidth(FontDesignMetrics.java:235)
2005-11-16 11:51:23,701 ERROR [STDERR] at sun.font.FontDesignMetrics.stringWidth(FontDesignMetrics.java:285)
2005-11-16 11:51:23,701 ERROR [STDERR] at com.sun.java.swing.SwingUtilities2.stringWidth(SwingUtilities2.java:292)
2005-11-16 11:51:23,701 ERROR [STDERR] at javax.swing.SwingUtilities.computeStringWidth(SwingUtilities.java:761)
...
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
Using this fonction in loop on several fonts and images while deleting the tmp font files in the jvm tmp dir :
private static boolean checkWidth(String text, Font font, Graphics graphics, int imgWidth) {
final FontMetrics fm = graphics.getFontMetrics(font);
final int width = SwingUtilities.computeStringWidth(fm, text);
return imgWidth > width;
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Using our own java.io.tmpdir directory and cleaning up the tmp files manually when the corresponding font file is not used any more solved the problem.
Here is a piece of code that produces the exception.
You need to place a directory called 'font' with more than 20 ttf fonts in
it (so at least 21) at the same level you compile and run this code (i don't
know if our fonts are special but I guess you can reproduce the problem with
any font files).
Compile and just run the test :
java -cp . CheckFontWidth
/*
* Copyright 2004 Mediabilis S.A.S., 135 rue de Billancourt,
* 92514 Boulogne-Billancourt, France
* www.mediabilis.com, ###@###.###
* All Rights Reserved.
*
* Created on 29 oct. 2004
*/
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.swing.SwingUtilities;
/**
*
* @version 1.0 29 oct. 2004
* @author j.guyard
*/
public class CheckFontWidth {
// Font cache map
private static Map fonts;
public static void main(String[] args) {
try {
// Init font cache
fonts = new HashMap();
// list font file names
File fontdir = new File("font");
String[] fontStrs = fontdir.list();
System.out.println("Nb of fonts = " + fontStrs.length);
Font font = null;
int i = 0;
BufferedImage img = new
BufferedImage(10,10,BufferedImage.TYPE_INT_RGB);
while (true)
{
System.out.println("i = " + i);
// get and cache next font
font = getFont("font/" + fontStrs[i++]);
// Use a text that changes (hour for instance)
String text = String.valueOf(System.currentTimeMillis());
// Compute width
int width =
SwingUtilities.computeStringWidth(img.createGraphics().getFontMetrics(font),
text);
// Reset counter and delete tmp file
if (i == (fontStrs.length)) {
System.out.println("Reset counter and delete tmp
file.");
i = 0;
File tmp = new
File(System.getProperties().getProperty("java.io.tmpdir"));
if (tmp.exists()) {
File[] tmpFiles = tmp.listFiles(new
FilenameFilter(){
public boolean accept(File file, String str) {
final String [] ext = str.split("[.]");
if (ext.length >= 2) {
return ext[ext.length-1].equals("tmp");
} else {
return false;
}
}
});
for (int j = 0; j < tmpFiles.length; j++) {
File file = tmpFiles[j];
file.delete();
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (FontFormatException e) {
e.printStackTrace();
}
}
// Font loading method
public static Font getFont(String path) throws IOException,
FontFormatException {
final File fontFile = new File(path);
final Font font;
if (!fonts.containsKey(path)) {
InputStream fontStream = null;
try {
fontStream = new FileInputStream(path);
font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
} finally {
if (null != fontStream) {
try {
fontStream.close();
} catch (IOException ioe) {
}
}
}
fonts.put(path, font);
} else {
font = (Font) fonts.get(path);
}
return font;
}
}
- backported by
-
JDK-2166640 Uncatchable recursive NullPointerException at sun.font.TrueTypeFont.open()
- Resolved
-
JDK-2166732 Uncatchable recursive NullPointerException at sun.font.TrueTypeFont.open()
- Resolved
-
JDK-2166606 Uncatchable recursive NullPointerException at sun.font.TrueTypeFont.open()
- Resolved
- relates to
-
JDK-6421149 Application hangs creating fonts
- Closed