diff --git a/doc/languages-frameworks/java.xml b/doc/languages-frameworks/java.xml
index bf0fc4883922..881d492b5bff 100644
--- a/doc/languages-frameworks/java.xml
+++ b/doc/languages-frameworks/java.xml
@@ -32,7 +32,7 @@ nativeBuildInputs = [ jdk ];
- If your Java package provides a program, you need to generate a wrapper script to run it using the OpenJRE. You can use makeWrapper for this:
+ If your Java package provides a program, you need to generate a wrapper script to run it using a JRE. You can use makeWrapper for this:
nativeBuildInputs = [ makeWrapper ];
@@ -43,7 +43,21 @@ installPhase =
--add-flags "-cp $out/share/java/foo.jar org.foo.Main"
'';
- Note the use of jre, which is the part of the OpenJDK package that contains the Java Runtime Environment. By using ${jre}/bin/java instead of ${jdk}/bin/java, you prevent your package from depending on the JDK at runtime.
+Since the introduction of the Java Platform Module System in Java 9, Java distributions typically no longer ship with a general-purpose JRE: instead, they allow generating a JRE with only the modules required for your application(s). Because we can't predict what modules will be needed on a general-purpose system, the default jre package is the full JDK. When building a minimal system/image, you can override the modules parameter on jre_minimal to build a JRE with only the modules relevant for you:
+
+let
+ my_jre = pkgs.jre_minimal.override {
+ modules = [
+ # The modules used by 'something' and 'other' combined:
+ "java.base"
+ "java.logging"
+ ];
+ };
+ something = (pkgs.something.override { jre = my_jre; });
+ other = (pkgs.other.override { jre = my_jre; });
+in
+ ...
+
diff --git a/pkgs/development/compilers/openjdk/jre.nix b/pkgs/development/compilers/openjdk/jre.nix
new file mode 100644
index 000000000000..817cdf9c26a9
--- /dev/null
+++ b/pkgs/development/compilers/openjdk/jre.nix
@@ -0,0 +1,19 @@
+{ jdk
+, runCommand
+, patchelf
+, lib
+, modules ? [ "java.base" ]
+}:
+
+let
+ jre = runCommand "${jdk.name}-jre" {
+ nativeBuildInputs = [ patchelf ];
+ buildInputs = [ jdk ];
+ passthru = {
+ home = "${jre}";
+ };
+ } ''
+ jlink --module-path ${jdk}/lib/openjdk/jmods --add-modules ${lib.concatStringsSep "," modules} --output $out
+ patchelf --shrink-rpath $out/bin/* $out/lib/jexec $out/lib/jspawnhelper $out/lib/*.so $out/lib/*/*.so
+ '';
+in jre
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 8fe1e4cd5253..6ffd2476c3bb 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -9267,10 +9267,19 @@ in
/* default JDK */
jdk = jdk14;
- # jdk14 lacks a jre output. See https://github.com/NixOS/nixpkgs/issues/79490
+
+ # Since the introduction of the Java Platform Module System in Java 9, Java
+ # no longer ships a separate JRE package.
+ #
+ # If you are building a 'minimal' system/image, you are encouraged to use
+ # 'jre_minimal' to build a bespoke JRE containing only the modules you need.
+ #
+ # For a general-purpose system, 'jre' defaults to the full JDK:
jre = jdk14;
jre_headless = jdk14_headless;
+ jre_minimal = callPackage ../development/compilers/openjdk/jre.nix { };
+
openjdk = openjdk14;
openjdk_headless = openjdk14_headless;