Sync java_tools, remote JDKs, and java toolchains in rules_java with Bazel HEAD

Update rules_java to match Bazel at HEAD

Sync toolchain changes

BUILD file

Fix local_java_repository

More fixes

Export WORKSPACE file

Expose //toolchains:srcs

fix determine_java_home

Fix remote JDK definitions

Update remoteJDK 17 versions to match Bazel sources

Make buildifier happy

Fix extensions.bzl

More fixes

Fix Bzlmod build

More fixes
diff --git a/BUILD b/BUILD
index 0fdc3cd..9840747 100644
--- a/BUILD
+++ b/BUILD
@@ -1,6 +1,9 @@
 licenses(["notice"])
 
-exports_files(["LICENSE"])
+exports_files([
+    "LICENSE",
+    "WORKSPACE",
+])
 
 filegroup(
     name = "distribution",
diff --git a/MODULE.bazel b/MODULE.bazel
index cd93b9b..8ee3664 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -31,7 +31,7 @@
 JDK_VERSIONS = [
     "11",
     "17",
-    "19",
+    "20",
 ]
 
 PLATFORMS = [
diff --git a/java/extensions.bzl b/java/extensions.bzl
index 01dabd8..5e456ed 100644
--- a/java/extensions.bzl
+++ b/java/extensions.bzl
@@ -13,13 +13,13 @@
 # limitations under the License.
 """Module extensions for rules_java."""
 
-load("//java:repositories.bzl", "java_tools_repos", "local_jdk_repo", "remote_jdk11_repos", "remote_jdk17_repos", "remote_jdk19_repos")
+load("//java:repositories.bzl", "java_tools_repos", "local_jdk_repo", "remote_jdk11_repos", "remote_jdk17_repos", "remote_jdk20_repos")
 
 def _toolchains_impl(_ctx):
     java_tools_repos()
     local_jdk_repo()
     remote_jdk11_repos()
     remote_jdk17_repos()
-    remote_jdk19_repos()
+    remote_jdk20_repos()
 
 toolchains = module_extension(implementation = _toolchains_impl)
diff --git a/java/repositories.bzl b/java/repositories.bzl
index 5b7a0d3..982be7f 100644
--- a/java/repositories.bzl
+++ b/java/repositories.bzl
@@ -16,6 +16,7 @@
 
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
+load("//toolchains:jdk_build_file.bzl", "JDK_BUILD_TEMPLATE")
 load("//toolchains:local_java_repository.bzl", "local_java_repository")
 load("//toolchains:remote_java_repository.bzl", "remote_java_repository")
 
@@ -24,50 +25,50 @@
     maybe(
         http_archive,
         name = "remote_java_tools",
-        sha256 = "0db35ec44745fd15b77d9df954e70a4fcf74554dd5bfe3f6e6cb6bbdc1f1c649",
+        sha256 = "cbb62ecfef61568ded46260a8e8e8430755db7ec9638c0c7ff668a656f6c042f",
         urls = [
-            "https://mirror.bazel.build/bazel_java_tools/releases/java/v12.1/java_tools-v12.1.zip",
-            "https://github.com/bazelbuild/java_tools/releases/download/java_v12.1/java_tools-v12.1.zip",
+            "https://mirror.bazel.build/bazel_java_tools/releases/java/v12.3/java_tools-v12.3.zip",
+            "https://github.com/bazelbuild/java_tools/releases/download/java_v12.3/java_tools-v12.3.zip",
         ],
     )
 
     maybe(
         http_archive,
         name = "remote_java_tools_linux",
-        sha256 = "093ecac3b42fcbc3621d08edc3ae3c8b0bc2bf56a0d9a85ddcdb1e0bcf10cbc7",
+        sha256 = "32157b5218b151009f5b99bf5e2f65e28823d269dfbba8cd57e7da5e7cdd291d",
         urls = [
-            "https://mirror.bazel.build/bazel_java_tools/releases/java/v12.1/java_tools_linux-v12.1.zip",
-            "https://github.com/bazelbuild/java_tools/releases/download/java_v12.1/java_tools_linux-v12.1.zip",
+            "https://mirror.bazel.build/bazel_java_tools/releases/java/v12.3/java_tools_linux-v12.3.zip",
+            "https://github.com/bazelbuild/java_tools/releases/download/java_v12.3/java_tools_linux-v12.3.zip",
         ],
     )
 
     maybe(
         http_archive,
         name = "remote_java_tools_windows",
-        sha256 = "1df7cc7fac54f437f43c24c019462e13058f394fdba5a64f566b92e8af18d0cf",
+        sha256 = "ec6f91387d2353eacb0ca0492f35f68c5c7b0e7a80acd1fb825088b4b069fab1",
         urls = [
-            "https://mirror.bazel.build/bazel_java_tools/releases/java/v12.1/java_tools_windows-v12.1.zip",
-            "https://github.com/bazelbuild/java_tools/releases/download/java_v12.1/java_tools_windows-v12.1.zip",
+            "https://mirror.bazel.build/bazel_java_tools/releases/java/v12.3/java_tools_windows-v12.3.zip",
+            "https://github.com/bazelbuild/java_tools/releases/download/java_v12.3/java_tools_windows-v12.3.zip",
         ],
     )
 
     maybe(
         http_archive,
         name = "remote_java_tools_darwin_x86_64",
-        sha256 = "16ca145203a62a1fcd6ae50513c0935d938591cb309b9b1172e257c57873f60d",
+        sha256 = "3c3fb1967a0f35c73ff509505de53ca4611518922a6b7c8c22a468aa7503132c",
         urls = [
-            "https://mirror.bazel.build/bazel_java_tools/releases/java/v12.1/java_tools_darwin_x86_64-v12.1.zip",
-            "https://github.com/bazelbuild/java_tools/releases/download/java_v12.1/java_tools_darwin_x86_64-v12.1.zip",
+            "https://mirror.bazel.build/bazel_java_tools/releases/java/v12.3/java_tools_darwin_x86_64-v12.3.zip",
+            "https://github.com/bazelbuild/java_tools/releases/download/java_v12.3/java_tools_darwin_x86_64-v12.3.zip",
         ],
     )
 
     maybe(
         http_archive,
         name = "remote_java_tools_darwin_arm64",
-        sha256 = "1d8e575e558782c2ceec0940e424f0e2df56b0df3d7fae68333eaceef2c4e41c",
+        sha256 = "29aa0c2de4e3cf45bc55d2995ba803ecbd1173a8d363860abbc309551db7931b",
         urls = [
-            "https://mirror.bazel.build/bazel_java_tools/releases/java/v12.1/java_tools_darwin_arm64-v12.1.zip",
-            "https://github.com/bazelbuild/java_tools/releases/download/java_v12.1/java_tools_darwin_arm64-v12.1.zip",
+            "https://mirror.bazel.build/bazel_java_tools/releases/java/v12.3/java_tools_darwin_arm64-v12.3.zip",
+            "https://github.com/bazelbuild/java_tools/releases/download/java_v12.3/java_tools_darwin_arm64-v12.3.zip",
         ],
     )
 
@@ -75,7 +76,7 @@
     maybe(
         local_java_repository,
         name = "local_jdk",
-        build_file = Label("//toolchains:jdk.BUILD"),
+        build_file_content = JDK_BUILD_TEMPLATE,
     )
 
 def remote_jdk8_repos(name = ""):
@@ -306,11 +307,59 @@
             "@platforms//os:linux",
             "@platforms//cpu:x86_64",
         ],
-        sha256 = "73d5c4bae20325ca41b606f7eae64669db3aac638c5b3ead4a975055846ad6de",
-        strip_prefix = "zulu17.32.13-ca-jdk17.0.2-linux_x64",
+        sha256 = "20c91a922eec795f3181eaa70def8b99d8eac56047c9a14bfb257c85b991df1b",
+        strip_prefix = "zulu17.38.21-ca-jdk17.0.5-linux_x64",
         urls = [
-            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.32.13-ca-jdk17.0.2-linux_x64.tar.gz",
-            "https://cdn.azul.com/zulu/bin/zulu17.32.13-ca-jdk17.0.2-linux_x64.tar.gz",
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.38.21-ca-jdk17.0.5-linux_x64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu17.38.21-ca-jdk17.0.5-linux_x64.tar.gz",
+        ],
+        version = "17",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk17_linux_aarch64",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:aarch64",
+        ],
+        sha256 = "dbc6ae9163e7ff469a9ab1f342cd1bc1f4c1fb78afc3c4f2228ee3b32c4f3e43",
+        strip_prefix = "zulu17.38.21-ca-jdk17.0.5-linux_aarch64",
+        urls = [
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.38.21-ca-jdk17.0.5-linux_aarch64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu17.38.21-ca-jdk17.0.5-linux_aarch64.tar.gz",
+        ],
+        version = "17",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk17_linux_s390x",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:s390x",
+        ],
+        sha256 = "fdc82f4b06c880762503b0cb40e25f46cf8190d06011b3b768f4091d3334ef7f",
+        strip_prefix = "jdk-17.0.4.1+1",
+        urls = [
+            "https://mirror.bazel.build/github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.4.1%2B1/OpenJDK17U-jdk_s390x_linux_hotspot_17.0.4.1_1.tar.gz",
+            "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.4.1%2B1/OpenJDK17U-jdk_s390x_linux_hotspot_17.0.4.1_1.tar.gz",
+        ],
+        version = "17",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk17_linux_ppc64le",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:ppc",
+        ],
+        sha256 = "cbedd0a1428b3058d156e99e8e9bc8769e0d633736d6776a4c4d9136648f2fd1",
+        strip_prefix = "jdk-17.0.4.1+1",
+        urls = [
+            "https://mirror.bazel.build/github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.4.1%2B1/OpenJDK17U-jdk_ppc64le_linux_hotspot_17.0.4.1_1.tar.gz",
+            "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.4.1%2B1/OpenJDK17U-jdk_ppc64le_linux_hotspot_17.0.4.1_1.tar.gz",
         ],
         version = "17",
     )
@@ -322,11 +371,11 @@
             "@platforms//os:macos",
             "@platforms//cpu:x86_64",
         ],
-        sha256 = "89d04b2d99b05dcb25114178e65f6a1c5ca742e125cab0a63d87e7e42f3fcb80",
-        strip_prefix = "zulu17.32.13-ca-jdk17.0.2-macosx_x64",
+        sha256 = "e6317cee4d40995f0da5b702af3f04a6af2bbd55febf67927696987d11113b53",
+        strip_prefix = "zulu17.38.21-ca-jdk17.0.5-macosx_x64",
         urls = [
-            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.32.13-ca-jdk17.0.2-macosx_x64.tar.gz",
-            "https://cdn.azul.com/zulu/bin/zulu17.32.13-ca-jdk17.0.2-macosx_x64.tar.gz",
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.38.21-ca-jdk17.0.5-macosx_x64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu17.38.21-ca-jdk17.0.5-macosx_x64.tar.gz",
         ],
         version = "17",
     )
@@ -338,11 +387,11 @@
             "@platforms//os:macos",
             "@platforms//cpu:aarch64",
         ],
-        sha256 = "54247dde248ffbcd3c048675504b1c503b81daf2dc0d64a79e353c48d383c977",
-        strip_prefix = "zulu17.32.13-ca-jdk17.0.2-macosx_aarch64",
+        sha256 = "515dd56ec99bb5ae8966621a2088aadfbe72631818ffbba6e4387b7ee292ab09",
+        strip_prefix = "zulu17.38.21-ca-jdk17.0.5-macosx_aarch64",
         urls = [
-            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.32.13-ca-jdk17.0.2-macosx_aarch64.tar.gz",
-            "https://cdn.azul.com/zulu/bin/zulu17.32.13-ca-jdk17.0.2-macosx_aarch64.tar.gz",
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.38.21-ca-jdk17.0.5-macosx_aarch64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu17.38.21-ca-jdk17.0.5-macosx_aarch64.tar.gz",
         ],
         version = "17",
     )
@@ -353,11 +402,11 @@
             "@platforms//os:windows",
             "@platforms//cpu:x86_64",
         ],
-        sha256 = "e965aa0ea7a0661a3446cf8f10ee00684b851f883b803315289f26b4aa907fdb",
-        strip_prefix = "zulu17.32.13-ca-jdk17.0.2-win_x64",
+        sha256 = "9972c5b62a61b45785d3d956c559e079d9e91f144ec46225f5deeda214d48f27",
+        strip_prefix = "zulu17.38.21-ca-jdk17.0.5-win_x64",
         urls = [
-            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.32.13-ca-jdk17.0.2-win_x64.zip",
-            "https://cdn.azul.com/zulu/bin/zulu17.32.13-ca-jdk17.0.2-win_x64.zip",
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.38.21-ca-jdk17.0.5-win_x64.zip",
+            "https://cdn.azul.com/zulu/bin/zulu17.38.21-ca-jdk17.0.5-win_x64.zip",
         ],
         version = "17",
     )
@@ -368,78 +417,94 @@
             "@platforms//os:windows",
             "@platforms//cpu:arm64",
         ],
-        sha256 = "811d7e7591bac4f081dfb00ba6bd15b6fc5969e1f89f0f327ef75147027c3877",
-        strip_prefix = "zulu17.30.15-ca-jdk17.0.1-win_aarch64",
+        sha256 = "bc3476f2161bf99bc9a243ff535b8fc033b34ce9a2fa4b62fb8d79b6bfdc427f",
+        strip_prefix = "zulu17.38.21-ca-jdk17.0.5-win_aarch64",
         urls = [
-            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.30.15-ca-jdk17.0.1-win_aarch64.zip",
-            "https://cdn.azul.com/zulu/bin/zulu17.30.15-ca-jdk17.0.1-win_aarch64.zip",
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.38.21-ca-jdk17.0.5-win_aarch64.zip",
+            "https://cdn.azul.com/zulu/bin/zulu17.38.21-ca-jdk17.0.5-win_aarch64.zip",
         ],
         version = "17",
     )
 
-def remote_jdk19_repos():
-    """Imports OpenJDK 19 repositories."""
+def remote_jdk20_repos():
+    """Imports OpenJDK 20 repositories."""
     maybe(
         remote_java_repository,
-        name = "remotejdk19_linux",
+        name = "remotejdk20_linux",
         target_compatible_with = [
             "@platforms//os:linux",
             "@platforms//cpu:x86_64",
         ],
-        sha256 = "4a994aded1d9b35258d543a59d4963d2687a1094a818b79a21f00273fbbc5bca",
-        strip_prefix = "zulu19.32.13-ca-jdk19.0.2-linux_x64",
+        sha256 = "0386418db7f23ae677d05045d30224094fc13423593ce9cd087d455069893bac",
+        strip_prefix = "zulu20.28.85-ca-jdk20.0.0-linux_x64",
         urls = [
-            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu19.32.13-ca-jdk19.0.2-linux_x64.tar.gz",
-            "https://cdn.azul.com/zulu/bin/zulu19.32.13-ca-jdk19.0.2-linux_x64.tar.gz",
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu20.28.85-ca-jdk20.0.0-linux_x64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu20.28.85-ca-jdk20.0.0-linux_x64.tar.gz",
         ],
-        version = "19",
+        version = "20",
     )
 
     maybe(
         remote_java_repository,
-        name = "remotejdk19_macos",
+        name = "remotejdk20_linux_aarch64",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:aarch64",
+        ],
+        sha256 = "47ce58ead9a05d5d53b96706ff6fa0eb2e46755ee67e2b416925e28f5b55038a",
+        strip_prefix = "zulu20.28.85-ca-jdk20.0.0-linux_aarch64",
+        urls = [
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu20.28.85-ca-jdk20.0.0-linux_aarch64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu20.28.85-ca-jdk20.0.0-linux_aarch64.tar.gz",
+        ],
+        version = "20",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk20_macos",
         target_compatible_with = [
             "@platforms//os:macos",
             "@platforms//cpu:x86_64",
         ],
-        sha256 = "2804575ae9ac63e39caa910e57610bf52b0f9e2d671928a98d18e2fcc9f62ac1",
-        strip_prefix = "zulu19.32.13-ca-jdk19.0.2-macosx_x64",
+        sha256 = "fde6cc17a194ea0d9b0c6c0cb6178199d8edfc282d649eec2c86a9796e843f86",
+        strip_prefix = "zulu20.28.85-ca-jdk20.0.0-macosx_x64",
         urls = [
-            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu19.32.13-ca-jdk19.0.2-macosx_x64.tar.gz",
-            "https://cdn.azul.com/zulu/bin/zulu19.32.13-ca-jdk19.0.2-macosx_x64.tar.gz",
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu20.28.85-ca-jdk20.0.0-macosx_x64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu20.28.85-ca-jdk20.0.0-macosx_x64.tar.gz",
         ],
-        version = "19",
+        version = "20",
     )
 
     maybe(
         remote_java_repository,
-        name = "remotejdk19_macos_aarch64",
+        name = "remotejdk20_macos_aarch64",
         target_compatible_with = [
             "@platforms//os:macos",
             "@platforms//cpu:aarch64",
         ],
-        sha256 = "177d058d968b2fbe7a5ff5eceb18cdc16f6376ce291004f1a3139e78b2fb6391",
-        strip_prefix = "zulu19.32.13-ca-jdk19.0.2-macosx_aarch64",
+        sha256 = "a2eff6a940c2df3a2352278027e83f5959f34dcfc8663034fe92be0f1b91ce6f",
+        strip_prefix = "zulu20.28.85-ca-jdk20.0.0-macosx_aarch64",
         urls = [
-            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu19.32.13-ca-jdk19.0.2-macosx_aarch64.tar.gz",
-            "https://cdn.azul.com/zulu/bin/zulu19.32.13-ca-jdk19.0.2-macosx_aarch64.tar.gz",
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu20.28.85-ca-jdk20.0.0-macosx_aarch64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu20.28.85-ca-jdk20.0.0-macosx_aarch64.tar.gz",
         ],
-        version = "19",
+        version = "20",
     )
     maybe(
         remote_java_repository,
-        name = "remotejdk19_win",
+        name = "remotejdk20_win",
         target_compatible_with = [
             "@platforms//os:windows",
             "@platforms//cpu:x86_64",
         ],
-        sha256 = "d6c768c5ec3252f936bd0562c25458f7c753c62835ca3e91166f975f7a5fe9f1",
-        strip_prefix = "zulu19.32.13-ca-jdk19.0.2-win_x64",
+        sha256 = "ac5f6a7d84dbbb0bb4d376feb331cc4c49a9920562f2a5e85b7a6b4863b10e1e",
+        strip_prefix = "zulu20.28.85-ca-jdk20.0.0-win_x64",
         urls = [
-            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu19.32.13-ca-jdk19.0.2-win_x64.zip",
-            "https://cdn.azul.com/zulu/bin/zulu19.32.13-ca-jdk19.0.2-win_x64.zip",
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu20.28.85-ca-jdk20.0.0-win_x64.zip",
+            "https://cdn.azul.com/zulu/bin/zulu20.28.85-ca-jdk20.0.0-win_x64.zip",
         ],
-        version = "19",
+        version = "20",
     )
 
 def rules_java_dependencies():
@@ -451,7 +516,7 @@
     local_jdk_repo()
     remote_jdk11_repos()
     remote_jdk17_repos()
-    remote_jdk19_repos()
+    remote_jdk20_repos()
     java_tools_repos()
 
 def rules_java_toolchains(name = "toolchains"):
@@ -460,7 +525,7 @@
     Args:
         name: The name of this macro (not used)
     """
-    JDK_VERSIONS = ["11", "17", "19"]
+    JDK_VERSIONS = ["11", "17", "20"]
     PLATFORMS = ["linux", "macos", "macos_aarch64", "win"]
 
     # Remote JDK repos for those Linux platforms are only defined for JDK 11.
diff --git a/toolchains/BUILD b/toolchains/BUILD
index 563c667..09211a4 100644
--- a/toolchains/BUILD
+++ b/toolchains/BUILD
@@ -22,7 +22,6 @@
 filegroup(
     name = "srcs",
     srcs = glob(["**"]),
-    visibility = ["//:__pkg__"],
 )
 
 # Used to distinguish toolchains used for Java development, ie the JavaToolchainProvider.
@@ -196,8 +195,8 @@
 bootclasspath(
     name = "platformclasspath",
     src = "DumpPlatformClassPath.java",
-    host_javabase = "current_java_runtime",
-    target_javabase = "current_java_runtime",
+    host_javabase = ":current_java_runtime",
+    target_javabase = ":current_java_runtime",
 )
 
 default_java_toolchain(
@@ -223,6 +222,15 @@
     for release in RELEASES
 ]
 
+# A toolchain that targets java 14.
+default_java_toolchain(
+    name = "toolchain_jdk_14",
+    configuration = dict(),
+    java_runtime = "//toolchains:remotejdk_14",
+    source_version = "14",
+    target_version = "14",
+)
+
 # A toolchain that targets java 15.
 default_java_toolchain(
     name = "toolchain_jdk_15",
@@ -250,6 +258,15 @@
     target_version = "17",
 )
 
+# A toolchain that targets java 20.
+default_java_toolchain(
+    name = "toolchain_jdk_20",
+    configuration = dict(),
+    java_runtime = "//toolchains:remotejdk_20",
+    source_version = "20",
+    target_version = "20",
+)
+
 default_java_toolchain(
     name = "prebuilt_toolchain",
     configuration = PREBUILT_TOOLCHAIN_CONFIGURATION,
@@ -280,3 +297,15 @@
     runtime_version = "remotejdk_17",
     visibility = ["//visibility:public"],
 )
+
+java_runtime_version_alias(
+    name = "remotejdk_20",
+    runtime_version = "remotejdk_20",
+    visibility = ["//visibility:public"],
+)
+
+java_runtime_version_alias(
+    name = "jdk_8",
+    runtime_version = "8",
+    visibility = ["//visibility:public"],
+)
diff --git a/toolchains/default_java_toolchain.bzl b/toolchains/default_java_toolchain.bzl
index 0d3d3d0..919b327 100644
--- a/toolchains/default_java_toolchain.bzl
+++ b/toolchains/default_java_toolchain.bzl
@@ -43,6 +43,11 @@
 
     # Compact strings make JavaBuilder slightly slower.
     "-XX:-CompactStrings",
+
+    # Since https://bugs.openjdk.org/browse/JDK-8153723, JVM logging goes to stdout. This
+    # makes it go to stderr instead.
+    "-Xlog:disable",
+    "-Xlog:all=warning:stderr:uptime,level,tags",
 ]
 
 JDK9_JVM_OPTS = BASE_JDK9_JVM_OPTS
@@ -162,6 +167,8 @@
                 toolchain_type = Label("@bazel_tools//tools/jdk:toolchain_type"),
                 target_settings = [name + "_default_version_setting"],
                 toolchain = name,
+                exec_compatible_with = exec_compatible_with,
+                target_compatible_with = target_compatible_with,
             )
 
         native.config_setting(
@@ -228,10 +235,14 @@
     args.add("--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED")
     args.add("--add-exports=jdk.compiler/com.sun.tools.javac.platform=ALL-UNNAMED")
     args.add("--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED")
-    args.add("-cp", class_dir.path)
+    args.add_all("-cp", [class_dir], expand_directories = False)
     args.add("DumpPlatformClassPath")
     args.add(bootclasspath)
 
+    system_files = ("release", "modules", "jrt-fs.jar")
+    system = [f for f in ctx.files.target_javabase if f.basename in system_files]
+    if len(system) != len(system_files):
+        system = None
     if ctx.attr.target_javabase:
         inputs.extend(ctx.files.target_javabase)
         args.add(ctx.attr.target_javabase[java_common.JavaRuntimeInfo].java_home)
@@ -245,6 +256,10 @@
     )
     return [
         DefaultInfo(files = depset([bootclasspath])),
+        java_common.BootClassPathInfo(
+            bootclasspath = [bootclasspath],
+            system = system,
+        ),
         OutputGroupInfo(jar = [bootclasspath]),
     ]
 
diff --git a/toolchains/jdk.BUILD b/toolchains/jdk.BUILD
deleted file mode 100644
index 287836a..0000000
--- a/toolchains/jdk.BUILD
+++ /dev/null
@@ -1,221 +0,0 @@
-load("@rules_java//java:defs.bzl", "java_import", "java_runtime")
-
-package(default_visibility = ["//visibility:public"])
-
-exports_files(["BUILD.bazel"])
-
-DEPRECATION_MESSAGE = ("Don't depend on targets in the JDK workspace;" +
-                       " use @bazel_tools//tools/jdk:current_java_runtime instead" +
-                       " (see https://github.com/bazelbuild/bazel/issues/5594)")
-
-filegroup(
-    name = "jni_header",
-    srcs = ["include/jni.h"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "jni_md_header-darwin",
-    srcs = ["include/darwin/jni_md.h"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "jni_md_header-linux",
-    srcs = ["include/linux/jni_md.h"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "jni_md_header-freebsd",
-    srcs = ["include/freebsd/jni_md.h"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "jni_md_header-openbsd",
-    srcs = ["include/openbsd/jni_md.h"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "jni_md_header-windows",
-    srcs = ["include/win32/jni_md.h"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "java",
-    srcs = select({
-        ":windows": ["bin/java.exe"],
-        "//conditions:default": ["bin/java"],
-    }),
-    data = [":jdk"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "jar",
-    srcs = select({
-        ":windows": ["bin/jar.exe"],
-        "//conditions:default": ["bin/jar"],
-    }),
-    data = [":jdk"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "javac",
-    srcs = select({
-        ":windows": ["bin/javac.exe"],
-        "//conditions:default": ["bin/javac"],
-    }),
-    data = [":jdk"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "javadoc",
-    srcs = select({
-        ":windows": ["bin/javadoc.exe"],
-        "//conditions:default": ["bin/javadoc"],
-    }),
-    data = [":jdk"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "xjc",
-    srcs = ["bin/xjc"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "wsimport",
-    srcs = ["bin/wsimport"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-BOOTCLASS_JARS = [
-    "rt.jar",
-    "resources.jar",
-    "jsse.jar",
-    "jce.jar",
-    "charsets.jar",
-]
-
-# TODO(cushon): this isn't compatible with JDK 9
-filegroup(
-    name = "bootclasspath",
-    srcs = ["jre/lib/%s" % jar for jar in BOOTCLASS_JARS],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "jre-bin",
-    srcs = select({
-        # In some configurations, Java browser plugin is considered harmful and
-        # common antivirus software blocks access to npjp2.dll interfering with Bazel,
-        # so do not include it in JRE on Windows.
-        ":windows": glob(
-            ["jre/bin/**"],
-            allow_empty = True,
-            exclude = ["jre/bin/plugin2/**"],
-        ),
-        "//conditions:default": glob(
-            ["jre/bin/**"],
-            allow_empty = True,
-        ),
-    }),
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "jre-lib",
-    srcs = glob(
-        ["jre/lib/**"],
-        allow_empty = True,
-    ),
-)
-
-filegroup(
-    name = "jre",
-    srcs = [":jre-default"],
-)
-
-filegroup(
-    name = "jre-default",
-    srcs = [
-        ":jre-bin",
-        ":jre-lib",
-    ],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-filegroup(
-    name = "jdk-bin",
-    srcs = glob(
-        ["bin/**"],
-        # The JDK on Windows sometimes contains a directory called
-        # "%systemroot%", which is not a valid label.
-        exclude = ["**/*%*/**"],
-    ),
-)
-
-#This folder holds security policies
-filegroup(
-    name = "jdk-conf",
-    srcs = glob(
-        ["conf/**"],
-        allow_empty = True,
-    ),
-)
-
-filegroup(
-    name = "jdk-include",
-    srcs = glob(
-        ["include/**"],
-        allow_empty = True,
-    ),
-)
-
-filegroup(
-    name = "jdk-lib",
-    srcs = glob(
-        ["lib/**"],
-        exclude = [
-            "lib/missioncontrol/**",
-            "lib/visualvm/**",
-        ],
-    ),
-)
-
-java_runtime(
-    name = "jdk",
-    srcs = [
-        ":jdk-bin",
-        ":jdk-conf",
-        ":jdk-include",
-        ":jdk-lib",
-        ":jre-default",
-    ],
-)
-
-filegroup(
-    name = "langtools",
-    srcs = ["lib/tools.jar"],
-    deprecation = DEPRECATION_MESSAGE,
-)
-
-java_import(
-    name = "langtools-neverlink",
-    deprecation = DEPRECATION_MESSAGE,
-    jars = ["lib/tools.jar"],
-    neverlink = 1,
-)
-
-config_setting(
-    name = "windows",
-    values = {"cpu": "x64_windows"},
-    visibility = ["//visibility:private"],
-)
diff --git a/toolchains/jdk_build_file.bzl b/toolchains/jdk_build_file.bzl
new file mode 100644
index 0000000..71b615a
--- /dev/null
+++ b/toolchains/jdk_build_file.bzl
@@ -0,0 +1,88 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""A templated BUILD file for Java repositories."""
+
+JDK_BUILD_TEMPLATE = """load("@rules_java//java:defs.bzl", "java_runtime")
+
+package(default_visibility = ["//visibility:public"])
+
+exports_files(["WORKSPACE", "BUILD.bazel"])
+
+filegroup(
+    name = "jre",
+    srcs = glob(
+        [
+            "jre/bin/**",
+            "jre/lib/**",
+        ],
+        allow_empty = True,
+        # In some configurations, Java browser plugin is considered harmful and
+        # common antivirus software blocks access to npjp2.dll interfering with Bazel,
+        # so do not include it in JRE on Windows.
+        exclude = ["jre/bin/plugin2/**"],
+    ),
+)
+
+filegroup(
+    name = "jdk-bin",
+    srcs = glob(
+        ["bin/**"],
+        # The JDK on Windows sometimes contains a directory called
+        # "%systemroot%", which is not a valid label.
+        exclude = ["**/*%*/**"],
+    ),
+)
+
+# This folder holds security policies.
+filegroup(
+    name = "jdk-conf",
+    srcs = glob(
+        ["conf/**"],
+        allow_empty = True,
+    ),
+)
+
+filegroup(
+    name = "jdk-include",
+    srcs = glob(
+        ["include/**"],
+        allow_empty = True,
+    ),
+)
+
+filegroup(
+    name = "jdk-lib",
+    srcs = glob(
+        ["lib/**", "release"],
+        allow_empty = True,
+        exclude = [
+            "lib/missioncontrol/**",
+            "lib/visualvm/**",
+        ],
+    ),
+)
+
+java_runtime(
+    name = "jdk",
+    srcs = [
+        ":jdk-bin",
+        ":jdk-conf",
+        ":jdk-include",
+        ":jdk-lib",
+        ":jre",
+    ],
+    version = {RUNTIME_VERSION},
+)
+"""
diff --git a/toolchains/local_java_repository.bzl b/toolchains/local_java_repository.bzl
index 9439115..faaced5 100644
--- a/toolchains/local_java_repository.bzl
+++ b/toolchains/local_java_repository.bzl
@@ -39,7 +39,7 @@
         return minor
     return major
 
-def local_java_runtime(name, java_home, version, runtime_name = None, visibility = ["//visibility:public"]):
+def local_java_runtime(name, java_home, version, runtime_name = None, visibility = ["//visibility:public"], exec_compatible_with = [], target_compatible_with = []):
     """Defines a java_runtime target together with Java runtime and compile toolchain definitions.
 
     Java runtime toolchain is constrained by flag --java_runtime_version having
@@ -56,6 +56,10 @@
       version: Version of the JDK.
       runtime_name: name of java_runtime target if it already exists.
       visibility: Visibility that will be applied to the java runtime target
+      exec_compatible_with: A list of constraint values that must be
+                            satisfied for the exec platform.
+      target_compatible_with: A list of constraint values that must be
+                              satisfied for the target platform.
     """
 
     if runtime_name == None:
@@ -64,6 +68,7 @@
             name = runtime_name,
             java_home = java_home,
             visibility = visibility,
+            version = int(version) if version.isdigit() else 0,
         )
 
     native.config_setting(
@@ -84,9 +89,9 @@
     native.alias(
         name = name + "_settings_alias",
         actual = select({
-            ":" + name + "_name_setting": ":" + name + "_name_setting",
-            ":" + name + "_version_setting": ":" + name + "_version_setting",
-            "//conditions:default": ":" + name + "_name_version_setting",
+            name + "_name_setting": name + "_name_setting",
+            name + "_version_setting": name + "_version_setting",
+            "//conditions:default": name + "_name_version_setting",
         }),
         visibility = ["//visibility:private"],
     )
@@ -104,6 +109,8 @@
                 source_version = str(version),
                 target_version = str(version),
                 java_runtime = runtime_name,
+                exec_compatible_with = exec_compatible_with,
+                target_compatible_with = target_compatible_with,
             )
 
     # else version is not recognized and no compilation toolchains are predefined
@@ -130,8 +137,7 @@
     if java_home:
         java_home_path = repository_ctx.path(java_home)
         if not java_home_path.exists:
-            fail('The path indicated by the "java_home" attribute "%s" (absolute: "%s") ' +
-                 "does not exist." % (java_home, str(java_home_path)))
+            fail('The path indicated by the "java_home" attribute "%s" (absolute: "%s") does not exist.' % (java_home, str(java_home_path)))
         return java_home_path
     if "JAVA_HOME" in repository_ctx.os.environ:
         return repository_ctx.path(repository_ctx.os.environ["JAVA_HOME"])
@@ -160,10 +166,13 @@
 
     java_home = _determine_java_home(repository_ctx)
 
+    # When Bzlmod is enabled, the Java runtime name should be the last segment of the repository name.
+    local_java_runtime_name = repository_ctx.name.split("~")[-1]
+
     repository_ctx.file(
         "WORKSPACE",
         "# DO NOT EDIT: automatically generated WORKSPACE file for local_java_repository\n" +
-        "workspace(name = \"{name}\")\n".format(name = repository_ctx.name),
+        "workspace(name = \"{name}\")\n".format(name = local_java_runtime_name),
     )
 
     java_bin = java_home.get_child("bin").get_child(_with_os_extension(repository_ctx, "java"))
@@ -173,7 +182,7 @@
         repository_ctx.file(
             "BUILD.bazel",
             _NOJDK_BUILD_TPL.format(
-                local_jdk = repository_ctx.name,
+                local_jdk = local_java_runtime_name,
                 java_binary = _with_os_extension(repository_ctx, "bin/java"),
                 java_home = java_home,
             ),
@@ -185,11 +194,17 @@
     version = repository_ctx.attr.version if repository_ctx.attr.version != "" else _detect_java_version(repository_ctx, java_bin)
 
     # Prepare BUILD file using "local_java_runtime" macro
-    build_file = ""
-    if repository_ctx.attr.build_file != None:
+    if repository_ctx.attr.build_file_content and repository_ctx.attr.build_file:
+        fail("build_file and build_file_content are exclusive")
+    if repository_ctx.attr.build_file_content:
+        build_file = repository_ctx.attr.build_file_content
+    elif repository_ctx.attr.build_file:
         build_file = repository_ctx.read(repository_ctx.path(repository_ctx.attr.build_file))
+    else:
+        build_file = ""
+    build_file = build_file.format(RUNTIME_VERSION = version if version.isdigit() else "0")
 
-    runtime_name = '"jdk"' if repository_ctx.attr.build_file else None
+    runtime_name = '"jdk"' if build_file else None
     local_java_runtime_macro = """
 local_java_runtime(
     name = "%s",
@@ -197,7 +212,7 @@
     java_home = "%s",
     version = "%s",
 )
-""" % (repository_ctx.attr.target_name, runtime_name, java_home, version)
+""" % (local_java_runtime_name, runtime_name, java_home, version)
 
     repository_ctx.file(
         "BUILD.bazel",
@@ -207,7 +222,7 @@
     )
 
     # Symlink all files
-    for file in java_home.readdir():
+    for file in repository_ctx.path(java_home).readdir():
         repository_ctx.symlink(file, file.basename)
 
 # Build file template, when JDK does not exist
@@ -217,7 +232,7 @@
    header = "Auto-Configuration Error:",
    message = ("Cannot find Java binary {java_binary} in {java_home}; either correct your JAVA_HOME, " +
           "PATH or specify Java from remote repository (e.g. " +
-          "--java_runtime_version=remotejdk_11")
+          "--java_runtime_version=remotejdk_11)")
 )
 config_setting(
    name = "localjdk_setting",
@@ -239,13 +254,13 @@
     environ = ["JAVA_HOME"],
     attrs = {
         "build_file": attr.label(),
+        "build_file_content": attr.string(),
         "java_home": attr.string(),
-        "target_name": attr.string(),
         "version": attr.string(),
     },
 )
 
-def local_java_repository(name, java_home = "", version = "", build_file = None):
+def local_java_repository(name, java_home = "", version = "", build_file = None, build_file_content = None):
     """Registers a runtime toolchain for local JDK and creates an unregistered compile toolchain.
 
     Toolchain resolution is constrained with --java_runtime_version flag
@@ -261,12 +276,7 @@
       name: A unique name for this rule.
       java_home: Location of the JDK imported.
       build_file: optionally BUILD file template
+      build_file_content: optional BUILD file template as a string
       version: optionally java version
     """
-    _local_java_repository_rule(
-        name = name,
-        target_name = name,
-        java_home = java_home,
-        version = version,
-        build_file = build_file,
-    )
+    _local_java_repository_rule(name = name, java_home = java_home, version = version, build_file = build_file, build_file_content = build_file_content)
diff --git a/toolchains/remote_java_repository.bzl b/toolchains/remote_java_repository.bzl
index 31b93b8..cbd8b13 100644
--- a/toolchains/remote_java_repository.bzl
+++ b/toolchains/remote_java_repository.bzl
@@ -18,6 +18,7 @@
 """
 
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("//toolchains:jdk_build_file.bzl", "JDK_BUILD_TEMPLATE")
 
 def _toolchain_config_impl(ctx):
     ctx.file("WORKSPACE", "workspace(name = \"{name}\")\n".format(name = ctx.name))
@@ -47,7 +48,7 @@
     """
     http_archive(
         name = name,
-        build_file = Label("//toolchains:jdk.BUILD"),
+        build_file_content = JDK_BUILD_TEMPLATE.format(RUNTIME_VERSION = version),
         **kwargs
     )
     _toolchain_config(
diff --git a/toolchains/toolchain_utils.bzl b/toolchains/toolchain_utils.bzl
new file mode 100644
index 0000000..7177092
--- /dev/null
+++ b/toolchains/toolchain_utils.bzl
@@ -0,0 +1,58 @@
+# Copyright 2019 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Finds the Java toolchain.
+
+Returns the toolchain if enabled, and falls back to a toolchain constructed from
+legacy toolchain selection.
+"""
+
+def find_java_toolchain(ctx, target):
+    """
+    Finds the Java toolchain.
+
+    If the Java toolchain is in use, returns it.  Otherwise, returns a Java
+    toolchain derived from legacy toolchain selection.
+
+    Args:
+      ctx: The rule context for which to find a toolchain.
+      target: A java_toolchain target (for legacy toolchain resolution).
+
+    Returns:
+      A JavaToolchainInfo.
+    """
+
+    _ignore = [ctx]  # buildifier: disable=unused-variable
+
+    return target[java_common.JavaToolchainInfo]
+
+def find_java_runtime_toolchain(ctx, target):
+    """
+    Finds the Java runtime.
+
+    If the Java toolchain is in use, returns it.  Otherwise, returns a Java
+    runtime derived from legacy toolchain selection.
+
+    Args:
+      ctx: The rule context for which to find a toolchain.
+      target: A java_runtime target (for legacy toolchain resolution).
+
+    Returns:
+      A JavaRuntimeInfo.
+    """
+
+    _ignore = [ctx]  # buildifier: disable=unused-variable
+
+    return target[java_common.JavaRuntimeInfo]