Font.createFont() and temporary files

Hi,

I have a servlet which uses the Font createFont(int, InputStream) method to overlay text on an image, which is sent to the client.

However, each time this method is invoked, a copy of the font as a temporary file is stored in c:\windows\temp. Closing the input stream has no effect, and the files only seem to disappear once JBoss/Tomcat is shut down.

Once the font is read and rendered, it is no longer required; how does one signal that this temporary file should be removed? I cannot believe that there is no mechanism designed to programmatically remove these.

(as a possibly amusing sidenote - I recently went on holiday for two weeks and had temporarily commented out the lines to cache already-generated images. I came back to find 6Gb of temporary files, all of them being copies of Verdana.ttf!)

Thanks,

Matt

PS. Yes, I realise that it's inefficient to be reading the font file every time I invoke the servlet - I will change this, but I still dislike the thought of having useless temporary files floating around.

[1077 byte] By [nullPaintera] at [2007-10-3 4:21:46]
# 1

What version JDK are you using?

Technically, temporary files are supposed to be deleted as soon as font object is garbage collected. However, there were several bugs that were recently fixed.

Please try latest JDK 6.0 build and see if problem is still reproducible.

As workaround if you are often using same fonts you may consider caching result of createFont for reuse.

neigora at 2007-7-14 22:23:59 > top of Java-index,Security,Cryptography...
# 2

Following on from what 'neigor' said I can confirm that there were some bugs

that prevented GC. SFAIK JDK 6 fixes all of them and most issues are

also fixed if you have the 1.5.0_07 patch or later whih contains the fix

6338472: Fonts created with createFont not being freed by GC.

I do however believe there is one other potential issue :(in AWT) in JDk1.5

(not 1.6) where AWT sometimes caches references to a font in

java.awt.Component. That can prevent them being freed but it

doesn't sound as if you are tripping over that one from your usage

I also have to wonder why on windows where verdana.ttf exists

as an installed font you need to use createFont at all?

Why not just say new Font("Verdana", ....) ?

philra at 2007-7-14 22:23:59 > top of Java-index,Security,Cryptography...
# 3

Thank you both so much for your help; I've upgraded from 1.5.0_06 to 1.5.0_08 and the temporary files are now correctly garbage collected.

There are several reasons why I am using an InputStream for loading the Verdana font; firstly, I believe it is best practice to write code that is platform-agnostic where possible. Secondly, I prefer to bundle dependent resources in the software itself rather than rely - or hope - on the target system having what the software is after (within reason, of course).

However, the pragmatic answer is that since Java's font kerning capabilities are less-than-desired (non-existant, even?), I am using iText to calculate font kerning. iText reads the ttf file itself, so rather than have a hard-coded reference to c:\windows\fonts\verdana.ttf (ick!) I decided to bundle the font with the software.

nullPaintera at 2007-7-14 22:23:59 > top of Java-index,Security,Cryptography...
# 4
Now that the problem is solved - why do you create a font instance every time for every request? Why not cache them? If you want to put a cap on the cache size, use LinkedHashMap.
kirillga at 2007-7-14 22:23:59 > top of Java-index,Security,Cryptography...
# 5
I forgot to mention; I'm also caching them now :)
nullPaintera at 2007-7-14 22:23:59 > top of Java-index,Security,Cryptography...
# 6
I hope you're not bundling Verdana.ttf with your app, MS may get upset...Dmitri
dmitri_trembovetskia at 2007-7-14 22:23:59 > top of Java-index,Security,Cryptography...
# 7
It's okay Dmitri; it's an internal application used exclusively within the organisation.
nullPaintera at 2007-7-14 22:23:59 > top of Java-index,Security,Cryptography...