Skip to content
Permalink
Browse files

8209113: Use WeakReference for lastFontStrike for created Fonts

Reviewed-by: serb, jdv
  • Loading branch information
Phil Race
Phil Race committed Dec 5, 2019
1 parent c96d36e commit 525b0422e42ac3442ba8642404d777ca3a206672
@@ -30,8 +30,10 @@
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 @@
* 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 FontStrike getStrike(Font font, FontRenderContext frc) {
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 @@ private FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
*/
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 @@ private FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
* 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 @@
class FontStrikeDisposer
implements DisposerRecord, Disposer.PollDisposable {

Font2D font2D;
ConcurrentHashMap<FontStrikeDesc, Reference<FontStrike>> strikeCache;
FontStrikeDesc desc;
long[] longGlyphImages;
int [] intGlyphImages;
@@ -65,36 +67,42 @@

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;
}

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;
}

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 FilenameFilter getType1Filter() {
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 Object run() {
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 @@ private static boolean fontSupportsEncoding(Font font, String encoding) {
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,22 +2305,36 @@ private static boolean fontSupportsEncoding(Font font, String encoding) {
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;
}
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:

0 comments on commit 525b042

Please sign in to comment.
You can’t perform that action at this time.