8209113: Use WeakReference for lastFontStrike for created Fonts
Reviewed-by: serb, jdv
This commit is contained in:
parent
c96d36e1b0
commit
525b0422e4
@ -30,8 +30,10 @@ import java.awt.font.FontRenderContext;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class Font2D {
|
||||
|
||||
@ -105,7 +107,22 @@ public abstract class Font2D {
|
||||
* This pre-supposes that a FontStrike is a shareable object, which
|
||||
* it should.
|
||||
*/
|
||||
protected Reference<FontStrike> lastFontStrike = new SoftReference<>(null);
|
||||
protected Reference<FontStrike> lastFontStrike = new WeakReference<>(null);
|
||||
|
||||
/*
|
||||
* if useWeak is true, proactively clear the cache after this
|
||||
* many strikes are present. 0 means leave it alone.
|
||||
*/
|
||||
private int strikeCacheMax = 0;
|
||||
/*
|
||||
* Whether to use weak refs for this font, even if soft refs is the default.
|
||||
*/
|
||||
private boolean useWeak;
|
||||
|
||||
void setUseWeakRefs(boolean weak, int maxStrikes) {
|
||||
this.useWeak = weak;
|
||||
this.strikeCacheMax = weak && maxStrikes > 0 ? maxStrikes : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* POSSIBLE OPTIMISATION:
|
||||
@ -304,6 +321,15 @@ public abstract class Font2D {
|
||||
return getStrike(desc, false);
|
||||
}
|
||||
|
||||
void updateLastStrikeRef(FontStrike strike) {
|
||||
lastFontStrike.clear();
|
||||
if (useWeak) {
|
||||
lastFontStrike = new WeakReference<>(strike);
|
||||
} else {
|
||||
lastFontStrike = new SoftReference<>(strike);
|
||||
}
|
||||
}
|
||||
|
||||
FontStrike getStrike(FontStrikeDesc desc) {
|
||||
return getStrike(desc, true);
|
||||
}
|
||||
@ -324,15 +350,13 @@ public abstract class Font2D {
|
||||
*/
|
||||
FontStrike strike = lastFontStrike.get();
|
||||
if (strike != null && desc.equals(strike.desc)) {
|
||||
//strike.lastlookupTime = System.currentTimeMillis();
|
||||
return strike;
|
||||
} else {
|
||||
Reference<FontStrike> strikeRef = strikeCache.get(desc);
|
||||
if (strikeRef != null) {
|
||||
strike = strikeRef.get();
|
||||
if (strike != null) {
|
||||
//strike.lastlookupTime = System.currentTimeMillis();
|
||||
lastFontStrike = new SoftReference<>(strike);
|
||||
updateLastStrikeRef(strike);
|
||||
StrikeCache.refStrike(strike);
|
||||
return strike;
|
||||
}
|
||||
@ -366,31 +390,21 @@ public abstract class Font2D {
|
||||
* which is what we want for what is likely a transient strike.
|
||||
*/
|
||||
int txType = desc.glyphTx.getType();
|
||||
if (txType == AffineTransform.TYPE_GENERAL_TRANSFORM ||
|
||||
if (useWeak ||
|
||||
txType == AffineTransform.TYPE_GENERAL_TRANSFORM ||
|
||||
(txType & AffineTransform.TYPE_GENERAL_ROTATION) != 0 &&
|
||||
strikeCache.size() > 10) {
|
||||
strikeRef = StrikeCache.getStrikeRef(strike, true);
|
||||
} else {
|
||||
strikeRef = StrikeCache.getStrikeRef(strike);
|
||||
strikeRef = StrikeCache.getStrikeRef(strike, useWeak);
|
||||
}
|
||||
strikeCache.put(desc, strikeRef);
|
||||
//strike.lastlookupTime = System.currentTimeMillis();
|
||||
lastFontStrike = new SoftReference<>(strike);
|
||||
updateLastStrikeRef(strike);
|
||||
StrikeCache.refStrike(strike);
|
||||
return strike;
|
||||
}
|
||||
}
|
||||
|
||||
void removeFromCache(FontStrikeDesc desc) {
|
||||
Reference<FontStrike> ref = strikeCache.get(desc);
|
||||
if (ref != null) {
|
||||
Object o = ref.get();
|
||||
if (o == null) {
|
||||
strikeCache.remove(desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The length of the metrics array must be >= 8. This method will
|
||||
* store the following elements in that array before returning:
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
package sun.font;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import sun.java2d.Disposer;
|
||||
import sun.java2d.DisposerRecord;
|
||||
|
||||
@ -53,7 +55,7 @@ import sun.java2d.DisposerRecord;
|
||||
class FontStrikeDisposer
|
||||
implements DisposerRecord, Disposer.PollDisposable {
|
||||
|
||||
Font2D font2D;
|
||||
ConcurrentHashMap<FontStrikeDesc, Reference<FontStrike>> strikeCache;
|
||||
FontStrikeDesc desc;
|
||||
long[] longGlyphImages;
|
||||
int [] intGlyphImages;
|
||||
@ -65,7 +67,7 @@ class FontStrikeDisposer
|
||||
|
||||
public FontStrikeDisposer(Font2D font2D, FontStrikeDesc desc,
|
||||
long pContext, int[] images) {
|
||||
this.font2D = font2D;
|
||||
this.strikeCache = font2D.strikeCache;
|
||||
this.desc = desc;
|
||||
this.pScalerContext = pContext;
|
||||
this.intGlyphImages = images;
|
||||
@ -73,7 +75,7 @@ class FontStrikeDisposer
|
||||
|
||||
public FontStrikeDisposer(Font2D font2D, FontStrikeDesc desc,
|
||||
long pContext, long[] images) {
|
||||
this.font2D = font2D;
|
||||
this.strikeCache = font2D.strikeCache;
|
||||
this.desc = desc;
|
||||
this.pScalerContext = pContext;
|
||||
this.longGlyphImages = images;
|
||||
@ -81,20 +83,26 @@ class FontStrikeDisposer
|
||||
|
||||
public FontStrikeDisposer(Font2D font2D, FontStrikeDesc desc,
|
||||
long pContext) {
|
||||
this.font2D = font2D;
|
||||
this.strikeCache = font2D.strikeCache;
|
||||
this.desc = desc;
|
||||
this.pScalerContext = pContext;
|
||||
}
|
||||
|
||||
public FontStrikeDisposer(Font2D font2D, FontStrikeDesc desc) {
|
||||
this.font2D = font2D;
|
||||
this.strikeCache = font2D.strikeCache;
|
||||
this.desc = desc;
|
||||
this.comp = true;
|
||||
}
|
||||
|
||||
public synchronized void dispose() {
|
||||
if (!disposed) {
|
||||
font2D.removeFromCache(desc);
|
||||
Reference<FontStrike> ref = strikeCache.get(desc);
|
||||
if (ref != null) {
|
||||
Object o = ref.get();
|
||||
if (o == null) {
|
||||
strikeCache.remove(desc);
|
||||
}
|
||||
}
|
||||
StrikeCache.disposeStrike(this);
|
||||
disposed = true;
|
||||
}
|
||||
|
@ -256,6 +256,13 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
return t1Filter;
|
||||
}
|
||||
|
||||
/* After we reach MAXSOFTREFCNT, use weak refs for created fonts.
|
||||
* This means that a small number of created fonts as used in a UI app
|
||||
* will not be eagerly collected, but an app that create many will
|
||||
* have them collected more frequently to reclaim storage.
|
||||
*/
|
||||
private static int maxSoftRefCnt = 10;
|
||||
|
||||
static {
|
||||
|
||||
java.security.AccessController.doPrivileged(
|
||||
@ -280,6 +287,9 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
System.getProperty("java.home","") + File.separator + "lib";
|
||||
jreFontDirName = jreLibDirName + File.separator + "fonts";
|
||||
|
||||
maxSoftRefCnt =
|
||||
Integer.getInteger("sun.java2d.font.maxSoftRefs", 10);
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@ -2283,6 +2293,8 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
Thread fileCloser = null;
|
||||
Vector<File> tmpFontFiles = null;
|
||||
|
||||
private int createdFontCount = 0;
|
||||
|
||||
public Font2D[] createFont2D(File fontFile, int fontFormat, boolean all,
|
||||
boolean isCopy, CreatedFontTracker tracker)
|
||||
throws FontFormatException {
|
||||
@ -2293,10 +2305,21 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
FileFont font2D = null;
|
||||
final File fFile = fontFile;
|
||||
final CreatedFontTracker _tracker = tracker;
|
||||
boolean weakRefs = false;
|
||||
int maxStrikes = 0;
|
||||
synchronized (this) {
|
||||
if (createdFontCount < maxSoftRefCnt) {
|
||||
createdFontCount++;
|
||||
} else {
|
||||
weakRefs = true;
|
||||
maxStrikes = 10;
|
||||
}
|
||||
}
|
||||
try {
|
||||
switch (fontFormat) {
|
||||
case Font.TRUETYPE_FONT:
|
||||
font2D = new TrueTypeFont(fontFilePath, null, 0, true);
|
||||
font2D.setUseWeakRefs(weakRefs, maxStrikes);
|
||||
fList.add(font2D);
|
||||
if (!all) {
|
||||
break;
|
||||
@ -2304,11 +2327,14 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
cnt = ((TrueTypeFont)font2D).getFontCount();
|
||||
int index = 1;
|
||||
while (index < cnt) {
|
||||
fList.add(new TrueTypeFont(fontFilePath, null, index++, true));
|
||||
font2D = new TrueTypeFont(fontFilePath, null, index++, true);
|
||||
font2D.setUseWeakRefs(weakRefs, maxStrikes);
|
||||
fList.add(font2D);
|
||||
}
|
||||
break;
|
||||
case Font.TYPE1_FONT:
|
||||
font2D = new Type1Font(fontFilePath, null, isCopy);
|
||||
font2D.setUseWeakRefs(weakRefs, maxStrikes);
|
||||
fList.add(font2D);
|
||||
break;
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user