-
Bug
-
Resolution: Fixed
-
P3
-
5.0
-
b03
-
x86
-
windows_xp
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2145749 | 6u2 | Philip Race | P3 | Resolved | Fixed | b01 |
JDK-2168681 | 5.0u17 | Abhijit Saha | P3 | Resolved | Fixed | b02 |
JDK-2165594 | 5.0u16-rev | Vikram Aroskar | P2 | Resolved | Fixed | b09 |
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 :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
The FontRenderContext that is given to the constructor of the LineBreakManager contains a AffineTransform object.
The 6 double values (scale/shear/transform) inside this AffineTransform object all are part of the key that is used to fill the static hashmap "SDCache" in class "sun.font.GlyphLayout".
The transform-x/y values in the AffineTransform are most of the cases different values, because different texts are painted on different points on the screen. The transform-x/y values are not needed by the LineBreakMeasurer: a string is just as long on any place on the screen.
In my app, eventually the static cache consumes 100MB of the java heap after it has been filled with 250000+ FontRenderContext objects!
In my opinion this is a slowly progressing memory leak.
OutOfMemory errors and a big windows VM size for java.exe are the result.
Solution: don't use the transforn-x/y values in the key in the hashmap.
I cleared then in the FontRenderContext before constructing the LineBreakMeasurer and the hashmap did not grow more than 3 FontRenderContext objects.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Use a LineBreakMeasurer object to measure text.
Use a new LineBreakMeasurer object for every consequtive text.
Supply the FontRenderContext that you get from a Graphics2D instance to the constructor for the LineBreakMeasurer.
But first set the Graphics2D context at the translation point for where you intend to paint the text on the screen. These coordinates will be different for each text you paint (else you cannot read the texts on the screen!)
You will see the number of sun.font.GlyphLayout$SDCache objects grow in your memory profiler. All these objects are held in a static hashmap, so garbage collection does not remove them from the heap.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would expect that caching would stay within limits.
Do not use the transform-x/y values in the key for the cache.
ACTUAL -
The transform-x/y values are used in the key for the cache and so the cache grows beyond proportions after enough time and repainting.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Moved to commments section.
REPRODUCIBILITY :
This bug can be reproduced always.
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 :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
The FontRenderContext that is given to the constructor of the LineBreakManager contains a AffineTransform object.
The 6 double values (scale/shear/transform) inside this AffineTransform object all are part of the key that is used to fill the static hashmap "SDCache" in class "sun.font.GlyphLayout".
The transform-x/y values in the AffineTransform are most of the cases different values, because different texts are painted on different points on the screen. The transform-x/y values are not needed by the LineBreakMeasurer: a string is just as long on any place on the screen.
In my app, eventually the static cache consumes 100MB of the java heap after it has been filled with 250000+ FontRenderContext objects!
In my opinion this is a slowly progressing memory leak.
OutOfMemory errors and a big windows VM size for java.exe are the result.
Solution: don't use the transforn-x/y values in the key in the hashmap.
I cleared then in the FontRenderContext before constructing the LineBreakMeasurer and the hashmap did not grow more than 3 FontRenderContext objects.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Use a LineBreakMeasurer object to measure text.
Use a new LineBreakMeasurer object for every consequtive text.
Supply the FontRenderContext that you get from a Graphics2D instance to the constructor for the LineBreakMeasurer.
But first set the Graphics2D context at the translation point for where you intend to paint the text on the screen. These coordinates will be different for each text you paint (else you cannot read the texts on the screen!)
You will see the number of sun.font.GlyphLayout$SDCache objects grow in your memory profiler. All these objects are held in a static hashmap, so garbage collection does not remove them from the heap.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would expect that caching would stay within limits.
Do not use the transform-x/y values in the key for the cache.
ACTUAL -
The transform-x/y values are used in the key for the cache and so the cache grows beyond proportions after enough time and repainting.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Moved to commments section.
REPRODUCIBILITY :
This bug can be reproduced always.
- backported by
-
JDK-2165594 static HashMap cache in LineBreakMeasurer can grow wihout bounds
- Resolved
-
JDK-2145749 static HashMap cache in LineBreakMeasurer can grow wihout bounds
- Resolved
-
JDK-2168681 static HashMap cache in LineBreakMeasurer can grow wihout bounds
- Resolved