|
Description
|
FULL PRODUCT VERSION :
Java(TM) SE Runtime Environment (build1.6.0-internal-fastdebug-tonyd_21_jul_2008_15_00-b00)
ADDITIONAL OS VERSION INFORMATION :
Os independent (will happen on any OS).
A DESCRIPTION OF THE PROBLEM :
There is a memory leak in j2se/src/share/classes/sun/font/StrikeCache.java which can occur when disposeStrike is called for a FontStrikeDisposer that has no glyph images. In this case, the memory allocated for the pScalerContext is never freed.
The fix is to add a final else if clause to free the scaler context at line 217.
e.g.:
static void disposeStrike(FontStrikeDisposer disposer) {
if (disposer.intGlyphImages != null) {
freeIntMemory(disposer.intGlyphImages,
disposer.pScalerContext);
} else if (disposer.longGlyphImages != null) {
freeLongMemory(disposer.longGlyphImages,
disposer.pScalerContext);
} else if (disposer.segIntGlyphImages != null) {
/* NB Now making multiple JNI calls in this case.
* But assuming that there's a reasonable amount of locality
* rather than sparse references then it should be OK.
*/
for (int i=0; i<disposer.segIntGlyphImages.length; i++) {
if (disposer.segIntGlyphImages[i] != null) {
freeIntMemory(disposer.segIntGlyphImages[i],
disposer.pScalerContext);
/* native will only free the scaler context once */
disposer.pScalerContext = 0L;
disposer.segIntGlyphImages[i] = null;
}
}
/* This may appear inefficient but it should only be invoked
* for a strike that never was asked to rasterise a glyph.
*/
if (disposer.pScalerContext != 0L) {
freeIntMemory(new int[0], disposer.pScalerContext);
}
} else if (disposer.segLongGlyphImages != null) {
for (int i=0; i<disposer.segLongGlyphImages.length; i++) {
if (disposer.segLongGlyphImages[i] != null) {
freeLongMemory(disposer.segLongGlyphImages[i],
disposer.pScalerContext);
disposer.pScalerContext = 0L;
disposer.segLongGlyphImages[i] = null;
}
}
if (disposer.pScalerContext != 0L) {
freeLongMemory(new long[0], disposer.pScalerContext);
}
}
// NEW ELSE IF CLAUSE HERE!
else if (disposer.pScalerContext != 0L) {
// tpd - If we never had glyph images, but we did allocate
// a scaler context, we must free the scaler context!
freeIntMemory(new int[0], disposer.pScalerContext);
}
It would be great if this fix could be integrated into an upcoming release!
Thanks,
Tony
REPRODUCIBILITY :
This bug can be reproduced always.
Posted Date : 2008-07-23 10:56:50.0
|
|
Evaluation
|
Suggested fix is partly correct. Needs distinguish the 32 bit and 64 bit cases :
} else if (disposer.pScalerContext != 0L) {
/* Rarely a strike may have been created that never cached
* any glyphs. In this case we still want to free the scaler
* context.
*/
if (FontManager.longAddresses) {
freeLongMemory(new long[0], disposer.pScalerContext);
} else {
freeIntMemory(new int[0], disposer.pScalerContext);
}
}
Posted Date : 2008-07-23 17:51:05.0
|