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;