EVALUATION
If the thread is being interrupted repeatedly, its possible we
end up with the same font filling a number of slots, and since
this code is called only from within an open() call, to register
that the font file is open for reading, its a bad idea to close() it
as happens here, since its destined for almost immediate use :
// is it possible for this to be the same font?
assert fontFileCache[lastPoolIndex] != font;
/* replace with new font, poolSize is unchanged. */
fontFileCache[lastPoolIndex].close();
fontFileCache[lastPoolIndex] = font;
Need to revise this code to detect the addition of duplicates.
I can also see how we can get a deadlock when updating the pool.
Its hard to capture this without fixing the first problem, after
which I was able to see an instance
Thread-A locks font1, then tries to acquire the pool lock
at sun.font.FontManager.addToPool(FontManager.java:287)
- waiting to lock <0xf47a6fb8> (a [Lsun.font.FileFont;)
at sun.font.TrueTypeFont.open(TrueTypeFont.java:282)
- locked <0xf485cec0> (a sun.font.TrueTypeFont)
at sun.font.TrueTypeFont.readBlock(TrueTypeFont.java:313)
- locked <0xf485cec0> (a sun.font.TrueTypeFont)
meanwhile Thread-B first acquires a lock on font2,
then the pool lock, and then needs the lock on font1 to close() it
and hence free it from the pool :
at sun.font.TrueTypeFont.close(TrueTypeFont.java:304)
- waiting to lock <0xf485cec0> (a sun.font.TrueTypeFont)
at sun.font.FontManager.addToPool(FontManager.java:309)
- locked <0xf47a6fb8> (a [Lsun.font.FileFont;)
at sun.font.TrueTypeFont.open(TrueTypeFont.java:282)
- locked <0xf485d5f0> (a sun.font.TrueTypeFont)
at sun.font.TrueTypeFont.getTableBuffer(TrueTypeFont.java:819)
- locked <0xf485d5f0> (a sun.font.TrueTypeFont)
The simplest fix here is for close() to be moved outside the synchronised block.
|