createFont() – how to forcefully remove unused fonts from memory?

(I’ll share MRE in a follow-up post, trying to think how best to summarise my code)

I have an art project which runs the createFont() function several times per frame – pulling random TTF/OTF files out of a folder containing thousands of fonts – and for some reason unknown to me (memory?) the sketch throws an Exception saying that a font is missing, when it’s clearly had no trouble finding it countless times before. The Exception can occur at anytime, almost immediately on launch, or after thousands of frames.

I’ve tried running my code using only one font – the same font over & over again – but even then, with createFont() being called several times per frame (as my sketch requires), the crash still occurs.

This is an example of the error I get during try{}:

Problem with createFont("/Volumes/macOS/Users/abc/Desktop/Font-Collection/xyz.ttf")
java.io.IOException: Problem reading font data.
        at java.desktop/java.awt.Font.createFont0(Font.java:1208)
        at java.desktop/java.awt.Font.createFont(Font.java:1076)
        at processing.core.PGraphics.createFont(PGraphics.java:4280)
        at processing.core.PApplet.createFont(PApplet.java:5983)
        at processing.core.PApplet.createFont(PApplet.java:5929)
        at fontchaos.fontChangerLines(fontchaos.java:204)
        at fontchaos.draw(fontchaos.java:176)
        at processing.core.PApplet.handleDraw(PApplet.java:2185)
        at processing.awt.PSurfaceAWT$9.callDraw(PSurfaceAWT.java:1440)
        at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:356)

…and – despite working under normal circumstances – a slightly different Exception appears related to my catch{} when the above try{} has failed:

The font "/Volumes/Evo2/processing/fontchaos/DIN Condensed Bold.ttf" is missing or inaccessible, make sure the URL is valid or that the file has been added to your sketch and is readable.
java.lang.RuntimeException: A null PFont was passed to textFont()
        at processing.core.PGraphics.textFont(PGraphics.java:4419)
        at processing.core.PApplet.textFont(PApplet.java:12714)
        at fontchaos.fontChangerLines(fontchaos.java:205)
        at fontchaos.draw(fontchaos.java:176)
        at processing.core.PApplet.handleDraw(PApplet.java:2185)
        at processing.awt.PSurfaceAWT$9.callDraw(PSurfaceAWT.java:1440)
        at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:356)
fontchaos.pde:189:0:189:0: RuntimeException: A null PFont was passed to textFont()
Finished.

Looking at Activity Monitor I have a hunch this has something to do with memory. The sketch has thousands of files open at the same time, 40GB+ of virtual memory in use etc. etc… so perhaps each time createFont() gets called the font files are shoved into memory but never released?

If anyone has any bright ideas, I’m all ears, thanks in advance!

1 Like

Hello @disuye.

There is a comment about this here:

:)

2 Likes

Hi @glv – I’ll read your link in a bit – but, yeah I’m aware that calling createFont() repeatedly in draw() is a no-no :slight_smile:

That being said, I am not looking for realtime performance – I render out TIFs and create a movie afterwards.

BTW: This github link is a much earlier version of my code (it’s changed a lot since) but you get the effect I am going for. I cannot think of a way to do this without calling createFont() in draw()?

FontChaos

Hello,

I was not able to run your example as is. I may try again pointing to directories on a W10 PC.

Consider:

Try this once you are done with the font:

myFont = null;

``:)’’

1 Like

Thanks for the reply! So a combination of your = null suggestion plus I just found out about forcing garbage collection (every 3~4 seconds) actually seems to be preventing crashes … I think. Will report back.

myFont = null;
if (frameCount % (3 * frameRate) == 1) {
    System.gc(); // Java garbage collection... pretty please?
} 

Have a great day.

1 Like

Hello @disuye,

I tried your code and it is stable for 151 fonts with Processing 4.0b8 and W10 Pro.

Software used:
https://visualvm.github.io/index.html

My experience with System.gc():
https://discourse.processing.org/t/pimage-garbage-not-being-properly-collected/12252/4
https://discourse.processing.org/t/insufficient-memory-for-java-sketch-on-raspberrypi/12331/2

:)

2 Likes

Many thanks for checking. The code on my github has been very stable.

Vs. my new sketch… it basically runs two instances of the fontchaos.pde → fontChanger() function, so I thought perhaps that’s where my issue originates, however stripping my code back to one instance of fontChanger() and the crashes still happen.

The error explicitly says ‘problem reading font data’ but evidently in my case that doesn’t mean there is anything actually wrong with the font, just how the data is being handled.

This is all way above my pay grade :slight_smile:

1 Like

A also thanks for the unexpected tip re: VisualVM! Never knew about that software, loving it already.

1 Like