In this article, I will try to briefly describe how Java Virtual Machine works with fonts. Once I needed to change the font used by the JVM and, surprisingly, found only pieces of legacy information about this. I spent a little time investigating the problem and now want to share this information with anybody who could find it useful. Feel free to leave any comments :)
First of all, let's agree on definitions:
TrueType - font technology, the way to describe fonts in vector format (
FreeType - library to transform vector fonts to bitmaps.
Logical font - front-end representation of fonts in Java;
Fontclass and its instances.
Physical font - font file in the system (e.g.
How letters are drawn?
The logical font is set in the Java program (manually or automatically during the creation of instances of some AWT/Swing classes). The five Java logical fonts Dialog, DialogInput, Monospaced, SansSerif and Serif must be supported by any JRE .
The next step happens during the execution of compiled Java Bytecode. JVM maps logical font onto the most suitable physical font available on the machine (JRE supports TrueType and PostScript Type 1 fonts). Mapping is done through a special mapfile (font configuration file). Old documentation says that font configuration files are located in
$JAVA_HOME/lib. One file is chosen depending on OS and OS version. If there is no suitable file then default
fontconfig.properties is chosen. 
I found that these files exist only in Oracle JDK (in
$JAVA_HOME/jre/lib/) and have names like
fontconfig.properties.src. There were no such files in other OpenJDK builds I investigated...
Tracing the execution of a simple Java program that works with fonts showed the following (this is true for all JDKs, including Oracle):
$ javac FontView.java $ strace -f java FontView &> out.txt $ grep open out.txt | grep properties ... [pid 24909] openat(AT_FDCWD, "/home/user/.java/fonts/1.8.0_222/fcinfo-1-pc-Ubuntu-16.04-en.properties", O_RDONLY) = 5
Here it is! The actual location of Java's font configuration file (mapfile) is
$HOME/.java/fonts/[version]. If there is no such file, JVM creates it automatically and fills it with the fonts matched with the help of
libfontconfig. This makes me believe that
$JAVA_HOME/jre/lib/fontconfig.properties.src) is some kind of legacy...
To draw physical fonts as accurately as possible, fontconfig library (
libfontconfig) is used. Long story short, vector fonts are configured with several configuration values, e.g. antialias, embolden, dpi, or size.
libfontconfig is used to deal with all these dependencies.
libfontconfig calls for FreeType library. Now the text is ready to be mapped from memory to our screen :)
How to change the font?
The simplest way is described. The whole system will use a directory with your desired fonts only.
fonts.conf is responsible for this (it tells which physical fonts are available for OS and programs). If you want a more advanced setup of
fonts.conf then read additional sources.
Install the desired physical font on the system (e.g. place
/etc/fonts/font.confcontains the line
<fontconfig>tag and there are no other
Remove old configuration file(s):
$ rm $HOME/.java/fonts/[version]/*
Run any program with text and fonts to create a new mapfile:
$ java FontView
Check that Java uses new physical font now:
$ cat $HOME/.java/fonts/[version]/[fontconfig file].properties