Traditionally it's been possible to build OpenJDK for FreeBSD either as the full Java Development Kit (JDK), or as the slimmed down Java Runtime Environment (JRE) via the FreeBSD ports system. This has been achieved by having two different ports, where the -jre port has been just a meta port that configures the main OpenJDK port for building the JRE instead. This has worked fine, and both the full OpenJDK and the JRE variant has been available both via ports and packages.
A requested feature has been to be able to build the headless version of OpenJDK as well. The headless version being a version of the JDK built without support for graphical user interfaces. This typically makes sense for servers, and other environments where you don't need a graphical user interface to begin with.
We could just add extra ports for this configuration as well, but since it possibly means adding another two ports (both for the full JDK and JRE headless versions) for every OpenJDK version, I thought it would make more sense to use the FLAVORS mechanism already built in to the FreeBSD ports system. At the cost of a slightly more complex port, it allows us to build all variants from a single Makefile.
We can specify the FLAVOR like this:
% make FLAVOR=jre
This will build the JRE version of the port. If no FLAVOR is specified, the full JDK is built by default.
The following FLAVORS are defined:
| FLAVOR | Description | Package suffix |
|---|---|---|
| jdk | Builds the full JDK including GUI support. This is the default if no FLAVOR is specified | |
| headless | Builds the full JDK without GUI support. | -headless |
| jre | Builds the JRE including GUI support. | -jre |
| jre_headless | Builds the JRE without GUI support. | -jre-headless |
So far, this has only been implemented for OpenJDK 25, but may be back-ported to older versions if the community thinks this is a good model for handling the various OpenJDK variants.
Which FLAVOR to choose?
If you ever only want to run Java programs, but have no need for compiling or debugging programs, installing the JRE will save you some storage space. Similarly, if you're not interested in running graphical programs, you'll be fine with the headless variant. In itself the headless version is not significantly smaller than one with GUI support, but it has fewer dependencies on graphics toolkits.
There's no reason to install more than one FLAVOR. Anything that works on the JRE will work on the full JDK, and anything that works on a headless variant will work on one with GUI support. So by installing the full JDK (the default) you'll always be covered. The FLAVORS are there to help slim down the install when you know that you will not need features that the default provides.
Some gotchas
The way FLAVORS is implemented in the OpenJDK 25 port at the moment, there's nothing preventing you from installing all FLAVORS at the same. This is because each FLAVOR installs to it's own sub directory which contains the package suffix. This could become problematic when other ports start depending on the different FLAVORS. While the packages won't conflict with each other, it will quickly eat up more than any space you saved by installing the JRE instead of the full JDK.
A discussion has been started on how to make the ports system handle this. One possible solution would be to have all FLAVORS install to the same sub directory and properly handle conflicts between them. The idea being that you will only ever have one flavor installed, but to ensure that works correctly the ports system and pkg have to know how flavors relate to each other. I.e it has to know that a dependency on the headless jre is satisfied if you have the full JDK already installed.
Alternatives?
Debian has a completely different way of packaging OpenJDK. At the surface we have the same four packages. As an example, the current OpenJDK packages on Debian Trixie are:
However, where this deviates from the approach we have taken on FreeBSD, is that these packages complement each other instead of being complete packages by themselves. That is, openjdk-21-jre depends on openjdk-21-jre-headless, and only contains the files it would add on top of the headless variant. Likewise openjdk-21-jdk depends on openjdk-21-jdk-headless and openjdk-21-jre. Again, it only contains the files not already installed by the dependencies.
Further, all the packages install to the same directories. Which is fine since they don't contain the same files, and will not overwrite each other.
This way, in the worst case you will only end up with the full JDK, never with duplicate installations of the same version in different flavors. As an additional bonus, the package servers don't have to build the same version multiple times in different flavors.
This may complicate packaging a bit, I think the savings both in build time and less bloated installations make it worth looking into.
Conclusions
The FLAVORS mechanism is a convenient way to build multiple variants of a port, but at least for the OpenJDK ports, it also has some non-trivial issues that needs to be considered. Personally I'm not sure it is the best way to package OpenJDK for FreeBSD, and think it could be worth considering other approaches. If you have ideas or thoughts about this issue, we'd love to hear about it, either in the discussion at reviews or via the freebsd-java mailing list.
Update: Fixes typos, thanks to LFA!