Initial import of rules_java. am: 4ba159a9c4 am: 640e0bdda9 am: fb2d8c8a4e am: 926d40d0a4 am: 31a90a6fb5 am: 00df52457a

Original change: https://android-review.googlesource.com/c/platform/external/bazelbuild-rules_java/+/2637269

Change-Id: Ib58c46b9c611de78b590e5a31cae2e904f33b449
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
new file mode 100644
index 0000000..cd90651
--- /dev/null
+++ b/.bazelci/presubmit.yml
@@ -0,0 +1,55 @@
+---
+build_targets: &build_targets
+  - "//..."
+  - "@remote_java_tools//java_tools/..."
+  # TODO: Look into broken targets in //toolchains
+  - "-//toolchains/..."
+
+build_targets_bzlmod: &build_targets_bzlmod
+  - "//..."
+  - "@remote_java_tools//java_tools/..."
+  - "-//toolchains/..."
+  # TODO(pcloudy): pkg_tar doesn't work with Bzlmod due to https://github.com/bazelbuild/bazel/issues/14259
+  # Enable once the issue is fixed.
+  - "-//distro/..."
+
+buildifier:
+  version: latest
+  warnings: "all"
+tasks:
+  ubuntu2004:
+    build_targets: *build_targets
+  macos:
+    build_targets: *build_targets
+  windows:
+    build_targets: *build_targets
+  ubuntu2004_head:
+    bazel: last_green
+    platform: ubuntu2004
+    build_targets: *build_targets
+  macos_head:
+    bazel: last_green
+    platform: macos
+    build_targets: *build_targets
+  windows_head:
+    bazel: last_green
+    platform: windows
+    build_targets: *build_targets
+  ubuntu2004_bzlmod:
+    bazel: last_green
+    platform: ubuntu2004
+    build_flags:
+      - "--config=bzlmod"
+    build_targets: *build_targets_bzlmod
+  macos_bzlmod:
+    bazel: last_green
+    platform: macos
+    build_flags:
+      - "--config=bzlmod"
+    build_targets: *build_targets_bzlmod
+  windows_bzlmod:
+    bazel: last_green
+    platform: windows
+    build_flags:
+      - "--config=bzlmod"
+    build_targets: *build_targets_bzlmod
diff --git a/.bazelrc b/.bazelrc
new file mode 100644
index 0000000..4fadfce
--- /dev/null
+++ b/.bazelrc
@@ -0,0 +1 @@
+build:bzlmod --experimental_enable_bzlmod
diff --git a/.bcr/metadata.template.json b/.bcr/metadata.template.json
new file mode 100644
index 0000000..41ba4c2
--- /dev/null
+++ b/.bcr/metadata.template.json
@@ -0,0 +1,9 @@
+{
+  "homepage": "https://github.com/bazelbuild/rules_java",
+  "maintainers": [],
+  "versions": [],
+  "yanked_versions": {},
+  "repository": [
+    "github:bazelbuild/rules_java"
+  ]
+}
diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml
new file mode 100644
index 0000000..52f713e
--- /dev/null
+++ b/.bcr/presubmit.yml
@@ -0,0 +1,8 @@
+matrix:
+  platform: ["centos7", "debian10", "macos", "ubuntu2004", "windows"]
+tasks:
+  verify_build_targets:
+    name: "Verify build targets"
+    platform: ${{ platform }}
+    build_targets:
+      - "@rules_java//java/..."
diff --git a/.bcr/source.template.json b/.bcr/source.template.json
new file mode 100644
index 0000000..095a9e8
--- /dev/null
+++ b/.bcr/source.template.json
@@ -0,0 +1,5 @@
+{
+  "integrity": "",
+  "strip_prefix": "",
+  "url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/rules_java-{TAG}.tar.gz"
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ef43625
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,19 @@
+# Ignore backup files.
+*~
+# Ignore Vim swap files.
+.*.swp
+# Ignore files generated by IDEs.
+/.classpath
+/.factorypath
+/.idea/
+/.ijwb/
+/.project
+/.settings
+# Ignore all bazel-* symlinks. There is no full list since this can change
+# based on the name of the directory bazel is cloned into.
+/bazel-*
+# Ignore outputs generated during Bazel bootstrapping.
+/output/
+# Ignore jekyll build output.
+/production
+/.sass-cache
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..8f95963
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,9 @@
+# This the official list of Bazel authors for copyright purposes.
+# This file is distinct from the CONTRIBUTORS files.
+# See the latter for an explanation.
+
+# Names should be added to this file as:
+# Name or Organization <email address>
+# The email address is not required for organizations.
+
+Google Inc.
diff --git a/BUILD b/BUILD
new file mode 100644
index 0000000..9840747
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,19 @@
+licenses(["notice"])
+
+exports_files([
+    "LICENSE",
+    "WORKSPACE",
+])
+
+filegroup(
+    name = "distribution",
+    srcs = [
+        "AUTHORS",
+        "BUILD",
+        "LICENSE",
+        "MODULE.bazel",
+        "//java:srcs",
+        "//toolchains:srcs",
+    ],
+    visibility = ["//distro:__pkg__"],
+)
diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644
index 0000000..1f7a7ed
--- /dev/null
+++ b/CODEOWNERS
@@ -0,0 +1,17 @@
+# Each line is a file pattern followed by one or more owners.
+
+# Order is important; the last matching pattern takes the most precedence.
+
+# When someone opens a pull request that only modifies files in directory, only
+# component owners and not the global owner(s) will be requested for a review.
+
+# Syntax: https://help.github.com/articles/about-codeowners/
+
+# Use individual usernames instead of teams (like @bazelbuild/android) for
+# auto-assignment to work, unless everyone in the team has write permissions to the repository.
+# See https://github.community/t5/How-to-use-Git-and-GitHub/CODEOWNERS-works-with-users-but-not-teams/td-p/4986
+
+# Component owners
+# ----------------
+
+* @comius @bazelbuild/java-team
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..db177d4
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,28 @@
+# How to Contribute
+
+We'd love to accept your patches and contributions to this project. There are
+just a few small guidelines you need to follow.
+
+## Contributor License Agreement
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement. You (or your employer) retain the copyright to your contribution;
+this simply gives us permission to use and redistribute your contributions as
+part of the project. Head over to <https://cla.developers.google.com/> to see
+your current agreements on file or to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+## Code reviews
+
+All submissions, including submissions by project members, require review. We
+use GitHub pull requests for this purpose. Consult
+[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
+information on using pull requests.
+
+## Community Guidelines
+
+This project follows
+[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..7414aa4
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,13 @@
+name: "rules_java"
+description:
+    "Bazel rules for building java code"
+
+third_party {
+  url {
+    type: GIT
+    value: "https://github.com/bazelbuild/rules_java"
+  }
+  version: "6.1.1"
+  last_upgrade_date { year: 2023 month: 6 day: 23 }
+  license_type: NOTICE
+}
diff --git a/MODULE.bazel b/MODULE.bazel
new file mode 100644
index 0000000..ebf3c8c
--- /dev/null
+++ b/MODULE.bazel
@@ -0,0 +1,75 @@
+module(
+    name = "rules_java",
+    version = "6.1.1",
+    compatibility_level = 1,
+)
+
+bazel_dep(name = "platforms", version = "0.0.4")
+bazel_dep(name = "rules_cc", version = "0.0.2")
+bazel_dep(name = "bazel_skylib", version = "1.2.0")
+
+# Required by @remote_java_tools, which is loaded via module extension.
+bazel_dep(name = "rules_proto", version = "4.0.0")
+bazel_dep(name = "rules_license", version = "0.0.3")
+
+register_toolchains("//toolchains:all")
+
+toolchains = use_extension("//java:extensions.bzl", "toolchains")
+
+# Declare remote java tools repos
+use_repo(toolchains, "remote_java_tools")
+use_repo(toolchains, "remote_java_tools_linux")
+use_repo(toolchains, "remote_java_tools_windows")
+use_repo(toolchains, "remote_java_tools_darwin_x86_64")
+use_repo(toolchains, "remote_java_tools_darwin_arm64")
+
+# Declare local jdk repo
+use_repo(toolchains, "local_jdk")
+
+register_toolchains("@local_jdk//:runtime_toolchain_definition")
+
+# Declare all remote jdk toolchain config repos
+JDKS = {
+    # Must match JDK repos defined in remote_jdk11_repos()
+    "11": [
+        "linux",
+        "linux_aarch64",
+        "linux_ppc64le",
+        "linux_s390x",
+        "macos",
+        "macos_aarch64",
+        "win",
+        "win_arm64",
+    ],
+    # Must match JDK repos defined in remote_jdk17_repos()
+    "17": [
+        "linux",
+        "linux_aarch64",
+        "linux_ppc64le",
+        "linux_s390x",
+        "macos",
+        "macos_aarch64",
+        "win",
+        "win_arm64",
+    ],
+    # Must match JDK repos defined in remote_jdk20_repos()
+    "20": [
+        "linux",
+        "linux_aarch64",
+        "macos",
+        "macos_aarch64",
+        "win",
+    ],
+}
+
+REMOTE_JDK_REPOS = [("remotejdk" + version + "_" + platform) for version in JDKS for platform in JDKS[version]]
+
+[use_repo(
+    toolchains,
+    repo + "_toolchain_config_repo",
+) for repo in REMOTE_JDK_REPOS]
+
+[register_toolchains("@" + name + "_toolchain_config_repo//:toolchain") for name in REMOTE_JDK_REPOS]
+
+# Dev dependencies
+bazel_dep(name = "rules_pkg", version = "0.5.1", dev_dependency = True)
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..f0f1277
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,3 @@
+include platform/build/bazel:/OWNERS
+jobredeaux@google.com
+agespino@google.com
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8c946de
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+# rules_java
+
+* Postsubmit [![Build status](https://badge.buildkite.com/d4f950ef5f481b8ca066624ba06c238fa1446d84a057ddbf89.svg?branch=master)](https://buildkite.com/bazel/rules-java-java)
+* Postsubmit + Current Bazel Incompatible Flags [![Build status](https://badge.buildkite.com/ef265d270238c02aff65106a0b861abb9265efacdf4af399c3.svg?branch=master)](https://buildkite.com/bazel/rules-java-plus-bazelisk-migrate)
+
+Java Rules for Bazel https://bazel.build.
diff --git a/WORKSPACE b/WORKSPACE
new file mode 100644
index 0000000..059716f
--- /dev/null
+++ b/WORKSPACE
@@ -0,0 +1,29 @@
+workspace(name = "rules_java")
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+    name = "bazel_skylib",
+    sha256 = "af87959afe497dc8dfd4c6cb66e1279cb98ccc84284619ebfec27d9c09a903de",
+    urls = [
+        "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.2.0/bazel-skylib-1.2.0.tar.gz",
+        "https://github.com/bazelbuild/bazel-skylib/releases/download/1.2.0/bazel-skylib-1.2.0.tar.gz",
+    ],
+)
+
+load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
+
+bazel_skylib_workspace()
+
+http_archive(
+    name = "rules_pkg",
+    sha256 = "a89e203d3cf264e564fcb96b6e06dd70bc0557356eb48400ce4b5d97c2c3720d",
+    urls = [
+        "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.5.1/rules_pkg-0.5.1.tar.gz",
+        "https://github.com/bazelbuild/rules_pkg/releases/download/0.5.1/rules_pkg-0.5.1.tar.gz",
+    ],
+)
+
+load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies")
+
+rules_pkg_dependencies()
diff --git a/WORKSPACE.bzlmod b/WORKSPACE.bzlmod
new file mode 100644
index 0000000..b021fa6
--- /dev/null
+++ b/WORKSPACE.bzlmod
@@ -0,0 +1,2 @@
+# A completely empty WORKSPACE file to replace the original WORKSPACE content when enabling Bzlmod.
+# No WORKSPACE prefix or suffix are added for this file.
diff --git a/distro/BUILD.bazel b/distro/BUILD.bazel
new file mode 100644
index 0000000..d136ca1
--- /dev/null
+++ b/distro/BUILD.bazel
@@ -0,0 +1,30 @@
+load("@rules_pkg//:pkg.bzl", "pkg_tar")
+load("@rules_pkg//releasing:defs.bzl", "print_rel_notes")
+load("//java:defs.bzl", "version")
+
+package(
+    default_visibility = ["//visibility:private"],
+)
+
+# Build the artifact to put on the github release page.
+pkg_tar(
+    name = "rules_java-%s" % version,
+    srcs = ["//:distribution"],
+    extension = "tar.gz",
+    # It is all source code, so make it read-only.
+    mode = "0444",
+    # Make it owned by root so it does not have the uid of the CI robot.
+    owner = "0.0",
+    package_dir = ".",
+    strip_prefix = ".",
+)
+
+print_rel_notes(
+    name = "relnotes",
+    outs = ["relnotes.txt"],
+    deps_method = "rules_java_dependencies",
+    repo = "rules_java",
+    setup_file = "java:repositories.bzl",
+    toolchains_method = "rules_java_toolchains",
+    version = version,
+)
diff --git a/distro/README.md b/distro/README.md
new file mode 100644
index 0000000..eb57af3
--- /dev/null
+++ b/distro/README.md
@@ -0,0 +1,9 @@
+# Releasing rules_java
+
+1. Update version in [java/defs.bzl](/java/defs.bzl),
+   [MODULE.bazel](/MODULE.bazel) and merge it
+2. Build the release running `bazel build //distro:rules_java-{version}`
+3. Prepare release notes running `bazel build //distro:relnotes`
+4. Create a new release on GitHub
+5. Copy/paste the produced `relnotes.txt` into the notes. Adjust as needed.
+6. Upload the produced tar.gz file as an artifact.
diff --git a/examples/hello_world/BUILD b/examples/hello_world/BUILD
new file mode 100644
index 0000000..282e2d7
--- /dev/null
+++ b/examples/hello_world/BUILD
@@ -0,0 +1,7 @@
+load("//java:defs.bzl", "java_binary")
+
+java_binary(
+    name = "hello_world",
+    srcs = ["com/google/HelloWorld.java"],
+    main_class = "com.google.HelloWorld",
+)
diff --git a/examples/hello_world/com/google/HelloWorld.java b/examples/hello_world/com/google/HelloWorld.java
new file mode 100644
index 0000000..5104eb0
--- /dev/null
+++ b/examples/hello_world/com/google/HelloWorld.java
@@ -0,0 +1,23 @@
+// Copyright 2021 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.
+package com.google;
+
+public class HelloWorld {
+
+  private HelloWorld() {}
+
+  public static void main (String[] args) {
+    System.out.println("Hello World!\n");
+  }
+}
diff --git a/java/BUILD b/java/BUILD
new file mode 100644
index 0000000..8e07ca3
--- /dev/null
+++ b/java/BUILD
@@ -0,0 +1,18 @@
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+filegroup(
+    name = "srcs",
+    srcs = glob(["**"]) + ["//java/private:srcs"],
+    visibility = ["//:__pkg__"],
+)
+
+bzl_library(
+    name = "rules",
+    srcs = ["defs.bzl"],
+    visibility = ["//visibility:public"],
+    deps = ["//java/private"],
+)
diff --git a/java/defs.bzl b/java/defs.bzl
new file mode 100644
index 0000000..bbfc55f
--- /dev/null
+++ b/java/defs.bzl
@@ -0,0 +1,154 @@
+# 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.
+"""Starlark rules for building Java projects."""
+
+load("//java/private:native.bzl", "NativeJavaInfo", "NativeJavaPluginInfo", "native_java_common")
+
+# Do not touch: This line marks the end of loads; needed for PR importing.
+
+_MIGRATION_TAG = "__JAVA_RULES_MIGRATION_DO_NOT_USE_WILL_BREAK__"
+version = "6.1.1"
+
+def _add_tags(attrs):
+    if "tags" in attrs and attrs["tags"] != None:
+        attrs["tags"] = attrs["tags"] + [_MIGRATION_TAG]
+    else:
+        attrs["tags"] = [_MIGRATION_TAG]
+    return attrs
+
+def java_binary(**attrs):
+    """Bazel java_binary rule.
+
+    https://docs.bazel.build/versions/master/be/java.html#java_binary
+
+    Args:
+      **attrs: Rule attributes
+    """
+
+    # buildifier: disable=native-java
+    native.java_binary(**_add_tags(attrs))
+
+def java_import(**attrs):
+    """Bazel java_import rule.
+
+    https://docs.bazel.build/versions/master/be/java.html#java_import
+
+    Args:
+      **attrs: Rule attributes
+    """
+
+    # buildifier: disable=native-java
+    native.java_import(**_add_tags(attrs))
+
+def java_library(**attrs):
+    """Bazel java_library rule.
+
+    https://docs.bazel.build/versions/master/be/java.html#java_library
+
+    Args:
+      **attrs: Rule attributes
+    """
+
+    # buildifier: disable=native-java
+    native.java_library(**_add_tags(attrs))
+
+def java_lite_proto_library(**attrs):
+    """Bazel java_lite_proto_library rule.
+
+    https://docs.bazel.build/versions/master/be/java.html#java_lite_proto_library
+
+    Args:
+      **attrs: Rule attributes
+    """
+
+    # buildifier: disable=native-java
+    native.java_lite_proto_library(**_add_tags(attrs))
+
+def java_proto_library(**attrs):
+    """Bazel java_proto_library rule.
+
+    https://docs.bazel.build/versions/master/be/java.html#java_proto_library
+
+    Args:
+      **attrs: Rule attributes
+    """
+
+    # buildifier: disable=native-java
+    native.java_proto_library(**_add_tags(attrs))
+
+def java_test(**attrs):
+    """Bazel java_test rule.
+
+    https://docs.bazel.build/versions/master/be/java.html#java_test
+
+    Args:
+      **attrs: Rule attributes
+    """
+
+    # buildifier: disable=native-java
+    native.java_test(**_add_tags(attrs))
+
+def java_package_configuration(**attrs):
+    """Bazel java_package_configuration rule.
+
+    https://docs.bazel.build/versions/master/be/java.html#java_package_configuration
+
+    Args:
+      **attrs: Rule attributes
+    """
+
+    # buildifier: disable=native-java
+    native.java_package_configuration(**_add_tags(attrs))
+
+def java_plugin(**attrs):
+    """Bazel java_plugin rule.
+
+    https://docs.bazel.build/versions/master/be/java.html#java_plugin
+
+    Args:
+      **attrs: Rule attributes
+    """
+
+    # buildifier: disable=native-java
+    native.java_plugin(**_add_tags(attrs))
+
+def java_runtime(**attrs):
+    """Bazel java_runtime rule.
+
+    https://docs.bazel.build/versions/master/be/java.html#java_runtime
+
+    Args:
+      **attrs: Rule attributes
+    """
+
+    # buildifier: disable=native-java
+    native.java_runtime(**_add_tags(attrs))
+
+def java_toolchain(**attrs):
+    """Bazel java_toolchain rule.
+
+    https://docs.bazel.build/versions/master/be/java.html#java_toolchain
+
+    Args:
+      **attrs: Rule attributes
+    """
+
+    # buildifier: disable=native-java
+    native.java_toolchain(**_add_tags(attrs))
+
+java_common = native_java_common
+
+JavaInfo = NativeJavaInfo
+
+JavaPluginInfo = NativeJavaPluginInfo
diff --git a/java/extensions.bzl b/java/extensions.bzl
new file mode 100644
index 0000000..5e456ed
--- /dev/null
+++ b/java/extensions.bzl
@@ -0,0 +1,25 @@
+# Copyright 2021 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.
+"""Module extensions for rules_java."""
+
+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_jdk20_repos()
+
+toolchains = module_extension(implementation = _toolchains_impl)
diff --git a/java/private/BUILD b/java/private/BUILD
new file mode 100644
index 0000000..9f50995
--- /dev/null
+++ b/java/private/BUILD
@@ -0,0 +1,15 @@
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+
+licenses(["notice"])
+
+bzl_library(
+    name = "private",
+    srcs = ["native.bzl"],
+    visibility = ["//java:__pkg__"],
+)
+
+filegroup(
+    name = "srcs",
+    srcs = glob(["**"]),
+    visibility = ["//java:__pkg__"],
+)
diff --git a/java/private/native.bzl b/java/private/native.bzl
new file mode 100644
index 0000000..64a4d5a
--- /dev/null
+++ b/java/private/native.bzl
@@ -0,0 +1,31 @@
+# Copyright 2022 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.
+
+# Redefine native symbols with a new name as a workaround for
+# exporting them in `//third_party/bazel_rules/rules_proto/proto:defs.bzl` with their original name.
+#
+# While we cannot force users to load these symbol due to the lack of a
+# allowlisting mechanism, we can still export them and tell users to
+# load it to make a future migration to pure Starlark easier.
+
+"""Lovely workaround to be able to expose native constants pretending to be Starlark."""
+
+# buildifier: disable=native-java
+native_java_common = java_common
+
+# buildifier: disable=native-java
+NativeJavaInfo = JavaInfo
+
+# buildifier: disable=native-java
+NativeJavaPluginInfo = JavaPluginInfo
diff --git a/java/repositories.bzl b/java/repositories.bzl
new file mode 100644
index 0000000..eaef6d7
--- /dev/null
+++ b/java/repositories.bzl
@@ -0,0 +1,557 @@
+# 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.
+
+"""Development and production dependencies of rules_java."""
+
+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")
+
+def java_tools_repos():
+    """ Declares the remote java_tools repositories """
+    maybe(
+        http_archive,
+        name = "remote_java_tools",
+        sha256 = "cbb62ecfef61568ded46260a8e8e8430755db7ec9638c0c7ff668a656f6c042f",
+        urls = [
+            "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 = "32157b5218b151009f5b99bf5e2f65e28823d269dfbba8cd57e7da5e7cdd291d",
+        urls = [
+            "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 = "ec6f91387d2353eacb0ca0492f35f68c5c7b0e7a80acd1fb825088b4b069fab1",
+        urls = [
+            "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 = "3c3fb1967a0f35c73ff509505de53ca4611518922a6b7c8c22a468aa7503132c",
+        urls = [
+            "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 = "29aa0c2de4e3cf45bc55d2995ba803ecbd1173a8d363860abbc309551db7931b",
+        urls = [
+            "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",
+        ],
+    )
+
+def local_jdk_repo():
+    maybe(
+        local_java_repository,
+        name = "local_jdk",
+        build_file_content = JDK_BUILD_TEMPLATE,
+    )
+
+def remote_jdk8_repos(name = ""):
+    """Imports OpenJDK 8 repositories.
+
+    Args:
+        name: The name of this macro (not used)
+    """
+    maybe(
+        remote_java_repository,
+        name = "remote_jdk8_linux_aarch64",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:aarch64",
+        ],
+        sha256 = "f4072e82faa5a09fab2accf2892d4684324fc999d614583c3ff785e87c03963f",
+        strip_prefix = "zulu8.50.51.263-ca-jdk8.0.275-linux_aarch64",
+        urls = [
+            "https://mirror.bazel.build/openjdk/azul-zulu-8.50.0.51-ca-jdk8.0.275/zulu8.50.51.263-ca-jdk8.0.275-linux_aarch64.tar.gz",
+            "https://cdn.azul.com/zulu-embedded/bin/zulu8.50.51.263-ca-jdk8.0.275-linux_aarch64.tar.gz",
+        ],
+        version = "8",
+    )
+    maybe(
+        remote_java_repository,
+        name = "remote_jdk8_linux_s390x",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:s390x",
+        ],
+        sha256 = "276a431c79b7e94bc1b1b4fd88523383ae2d635ea67114dfc8a6174267f8fb2c",
+        strip_prefix = "jdk8u292-b10",
+        urls = [
+            "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jdk_s390x_linux_hotspot_8u292b10.tar.gz",
+        ],
+        version = "8",
+    )
+    maybe(
+        remote_java_repository,
+        name = "remote_jdk8_linux",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:x86_64",
+        ],
+        sha256 = "1db6b2fa642950ee1b4b1ec2b6bc8a9113d7a4cd723f79398e1ada7dab1c981c",
+        strip_prefix = "zulu8.50.0.51-ca-jdk8.0.275-linux_x64",
+        urls = [
+            "https://mirror.bazel.build/openjdk/azul-zulu-8.50.0.51-ca-jdk8.0.275/zulu8.50.0.51-ca-jdk8.0.275-linux_x64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu8.50.0.51-ca-jdk8.0.275-linux_x64.tar.gz",
+        ],
+        version = "8",
+    )
+    maybe(
+        remote_java_repository,
+        name = "remote_jdk8_macos_aarch64",
+        target_compatible_with = [
+            "@platforms//os:macos",
+            "@platforms//cpu:aarch64",
+        ],
+        sha256 = "e5c84a46bbd985c3a53358db9c97a6fd4930f92b833c3163a0d1e47dab59768c",
+        strip_prefix = "zulu8.62.0.19-ca-jdk8.0.332-macosx_aarch64",
+        urls = [
+            "https://cdn.azul.com/zulu/bin/zulu8.62.0.19-ca-jdk8.0.332-macosx_aarch64.tar.gz",
+        ],
+        version = "8",
+    )
+    maybe(
+        remote_java_repository,
+        name = "remote_jdk8_macos",
+        target_compatible_with = [
+            "@platforms//os:macos",
+            "@platforms//cpu:x86_64",
+        ],
+        sha256 = "b03176597734299c9a15b7c2cc770783cf14d121196196c1248e80c026b59c17",
+        strip_prefix = "zulu8.50.0.51-ca-jdk8.0.275-macosx_x64",
+        urls = [
+            "https://mirror.bazel.build/openjdk/azul-zulu-8.50.0.51-ca-jdk8.0.275/zulu8.50.0.51-ca-jdk8.0.275-macosx_x64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu8.50.0.51-ca-jdk8.0.275-macosx_x64.tar.gz",
+        ],
+        version = "8",
+    )
+    maybe(
+        remote_java_repository,
+        name = "remote_jdk8_windows",
+        target_compatible_with = [
+            "@platforms//os:windows",
+            "@platforms//cpu:x86_64",
+        ],
+        sha256 = "49759b2bd2ab28231a21ff3a3bb45824ddef55d89b5b1a05a62e26a365da0774",
+        strip_prefix = "zulu8.50.0.51-ca-jdk8.0.275-win_x64",
+        urls = [
+            "https://mirror.bazel.build/openjdk/azul-zulu-8.50.0.51-ca-jdk8.0.275/zulu8.50.0.51-ca-jdk8.0.275-win_x64.zip",
+            "https://cdn.azul.com/zulu/bin/zulu8.50.0.51-ca-jdk8.0.275-win_x64.zip",
+        ],
+        version = "8",
+    )
+    REMOTE_JDK8_REPOS = [
+        "remote_jdk8_linux_aarch64",
+        "remote_jdk8_linux_s390x",
+        "remote_jdk8_linux",
+        "remote_jdk8_macos_aarch64",
+        "remote_jdk8_macos",
+        "remote_jdk8_windows",
+    ]
+    for name in REMOTE_JDK8_REPOS:
+        native.register_toolchains("@" + name + "_toolchain_config_repo//:toolchain")
+
+def remote_jdk11_repos():
+    """Imports OpenJDK 11 repositories."""
+    maybe(
+        remote_java_repository,
+        name = "remotejdk11_linux",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:x86_64",
+        ],
+        sha256 = "e064b61d93304012351242bf0823c6a2e41d9e28add7ea7f05378b7243d34247",
+        strip_prefix = "zulu11.56.19-ca-jdk11.0.15-linux_x64",
+        urls = [
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu11.56.19-ca-jdk11.0.15-linux_x64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu11.56.19-ca-jdk11.0.15-linux_x64.tar.gz",
+        ],
+        version = "11",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk11_linux_aarch64",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:aarch64",
+        ],
+        sha256 = "fc7c41a0005180d4ca471c90d01e049469e0614cf774566d4cf383caa29d1a97",
+        strip_prefix = "zulu11.56.19-ca-jdk11.0.15-linux_aarch64",
+        urls = [
+            "https://mirror.bazel.build/cdn.azul.com/zulu-embedded/bin/zulu11.56.19-ca-jdk11.0.15-linux_aarch64.tar.gz",
+            "https://cdn.azul.com/zulu-embedded/bin/zulu11.56.19-ca-jdk11.0.15-linux_aarch64.tar.gz",
+        ],
+        version = "11",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk11_linux_ppc64le",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:ppc",
+        ],
+        sha256 = "a8fba686f6eb8ae1d1a9566821dbd5a85a1108b96ad857fdbac5c1e4649fc56f",
+        strip_prefix = "jdk-11.0.15+10",
+        urls = [
+            "https://mirror.bazel.build/github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.15+10/OpenJDK11U-jdk_ppc64le_linux_hotspot_11.0.15_10.tar.gz",
+            "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.15+10/OpenJDK11U-jdk_ppc64le_linux_hotspot_11.0.15_10.tar.gz",
+        ],
+        version = "11",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk11_linux_s390x",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:s390x",
+        ],
+        sha256 = "a58fc0361966af0a5d5a31a2d8a208e3c9bb0f54f345596fd80b99ea9a39788b",
+        strip_prefix = "jdk-11.0.15+10",
+        urls = [
+            "https://mirror.bazel.build/github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.15+10/OpenJDK11U-jdk_s390x_linux_hotspot_11.0.15_10.tar.gz",
+            "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.15+10/OpenJDK11U-jdk_s390x_linux_hotspot_11.0.15_10.tar.gz",
+        ],
+        version = "11",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk11_macos",
+        target_compatible_with = [
+            "@platforms//os:macos",
+            "@platforms//cpu:x86_64",
+        ],
+        sha256 = "2614e5c5de8e989d4d81759de4c333aa5b867b17ab9ee78754309ba65c7f6f55",
+        strip_prefix = "zulu11.56.19-ca-jdk11.0.15-macosx_x64",
+        urls = [
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu11.56.19-ca-jdk11.0.15-macosx_x64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu11.56.19-ca-jdk11.0.15-macosx_x64.tar.gz",
+        ],
+        version = "11",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk11_macos_aarch64",
+        target_compatible_with = [
+            "@platforms//os:macos",
+            "@platforms//cpu:aarch64",
+        ],
+        sha256 = "6bb0d2c6e8a29dcd9c577bbb2986352ba12481a9549ac2c0bcfd00ed60e538d2",
+        strip_prefix = "zulu11.56.19-ca-jdk11.0.15-macosx_aarch64",
+        urls = [
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu11.56.19-ca-jdk11.0.15-macosx_aarch64.tar.gz",
+            "https://cdn.azul.com/zulu/bin/zulu11.56.19-ca-jdk11.0.15-macosx_aarch64.tar.gz",
+        ],
+        version = "11",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk11_win",
+        target_compatible_with = [
+            "@platforms//os:windows",
+            "@platforms//cpu:x86_64",
+        ],
+        sha256 = "a106c77389a63b6bd963a087d5f01171bd32aa3ee7377ecef87531390dcb9050",
+        strip_prefix = "zulu11.56.19-ca-jdk11.0.15-win_x64",
+        urls = [
+            "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu11.56.19-ca-jdk11.0.15-win_x64.zip",
+            "https://cdn.azul.com/zulu/bin/zulu11.56.19-ca-jdk11.0.15-win_x64.zip",
+        ],
+        version = "11",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk11_win_arm64",
+        target_compatible_with = [
+            "@platforms//os:windows",
+            "@platforms//cpu:arm64",
+        ],
+        sha256 = "b8a28e6e767d90acf793ea6f5bed0bb595ba0ba5ebdf8b99f395266161e53ec2",
+        strip_prefix = "jdk-11.0.13+8",
+        urls = [
+            "https://mirror.bazel.build/aka.ms/download-jdk/microsoft-jdk-11.0.13.8.1-windows-aarch64.zip",
+        ],
+        version = "11",
+    )
+
+def remote_jdk17_repos():
+    """Imports OpenJDK 17 repositories."""
+    maybe(
+        remote_java_repository,
+        name = "remotejdk17_linux",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:x86_64",
+        ],
+        sha256 = "20c91a922eec795f3181eaa70def8b99d8eac56047c9a14bfb257c85b991df1b",
+        strip_prefix = "zulu17.38.21-ca-jdk17.0.5-linux_x64",
+        urls = [
+            "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",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk17_macos",
+        target_compatible_with = [
+            "@platforms//os:macos",
+            "@platforms//cpu:x86_64",
+        ],
+        sha256 = "e6317cee4d40995f0da5b702af3f04a6af2bbd55febf67927696987d11113b53",
+        strip_prefix = "zulu17.38.21-ca-jdk17.0.5-macosx_x64",
+        urls = [
+            "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",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk17_macos_aarch64",
+        target_compatible_with = [
+            "@platforms//os:macos",
+            "@platforms//cpu: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.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",
+    )
+    maybe(
+        remote_java_repository,
+        name = "remotejdk17_win",
+        target_compatible_with = [
+            "@platforms//os:windows",
+            "@platforms//cpu:x86_64",
+        ],
+        sha256 = "9972c5b62a61b45785d3d956c559e079d9e91f144ec46225f5deeda214d48f27",
+        strip_prefix = "zulu17.38.21-ca-jdk17.0.5-win_x64",
+        urls = [
+            "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",
+    )
+    maybe(
+        remote_java_repository,
+        name = "remotejdk17_win_arm64",
+        target_compatible_with = [
+            "@platforms//os:windows",
+            "@platforms//cpu:arm64",
+        ],
+        sha256 = "bc3476f2161bf99bc9a243ff535b8fc033b34ce9a2fa4b62fb8d79b6bfdc427f",
+        strip_prefix = "zulu17.38.21-ca-jdk17.0.5-win_aarch64",
+        urls = [
+            "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_jdk20_repos():
+    """Imports OpenJDK 20 repositories."""
+    maybe(
+        remote_java_repository,
+        name = "remotejdk20_linux",
+        target_compatible_with = [
+            "@platforms//os:linux",
+            "@platforms//cpu:x86_64",
+        ],
+        sha256 = "0386418db7f23ae677d05045d30224094fc13423593ce9cd087d455069893bac",
+        strip_prefix = "zulu20.28.85-ca-jdk20.0.0-linux_x64",
+        urls = [
+            "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 = "20",
+    )
+
+    maybe(
+        remote_java_repository,
+        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 = "fde6cc17a194ea0d9b0c6c0cb6178199d8edfc282d649eec2c86a9796e843f86",
+        strip_prefix = "zulu20.28.85-ca-jdk20.0.0-macosx_x64",
+        urls = [
+            "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 = "20",
+    )
+
+    maybe(
+        remote_java_repository,
+        name = "remotejdk20_macos_aarch64",
+        target_compatible_with = [
+            "@platforms//os:macos",
+            "@platforms//cpu:aarch64",
+        ],
+        sha256 = "a2eff6a940c2df3a2352278027e83f5959f34dcfc8663034fe92be0f1b91ce6f",
+        strip_prefix = "zulu20.28.85-ca-jdk20.0.0-macosx_aarch64",
+        urls = [
+            "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 = "20",
+    )
+    maybe(
+        remote_java_repository,
+        name = "remotejdk20_win",
+        target_compatible_with = [
+            "@platforms//os:windows",
+            "@platforms//cpu:x86_64",
+        ],
+        sha256 = "ac5f6a7d84dbbb0bb4d376feb331cc4c49a9920562f2a5e85b7a6b4863b10e1e",
+        strip_prefix = "zulu20.28.85-ca-jdk20.0.0-win_x64",
+        urls = [
+            "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 = "20",
+    )
+
+def rules_java_dependencies():
+    """An utility method to load all dependencies of rules_java.
+
+    Loads the remote repositories used by default in Bazel.
+    """
+
+    local_jdk_repo()
+    remote_jdk11_repos()
+    remote_jdk17_repos()
+    remote_jdk20_repos()
+    java_tools_repos()
+
+def rules_java_toolchains(name = "toolchains"):
+    """An utility method to load all Java toolchains.
+
+    Args:
+        name: The name of this macro (not used)
+    """
+    JDKS = {
+        # Must match JDK repos defined in remote_jdk11_repos()
+        "11": ["linux", "linux_aarch64", "linux_ppc64le", "linux_s390x", "macos", "macos_aarch64", "win", "win_arm64"],
+        # Must match JDK repos defined in remote_jdk17_repos()
+        "17": ["linux", "linux_aarch64", "linux_ppc64le", "linux_s390x", "macos", "macos_aarch64", "win", "win_arm64"],
+        # Must match JDK repos defined in remote_jdk20_repos()
+        "20": ["linux", "linux_aarch64", "macos", "macos_aarch64", "win"],
+    }
+
+    REMOTE_JDK_REPOS = [("remotejdk" + version + "_" + platform) for version in JDKS for platform in JDKS[version]]
+
+    native.register_toolchains("//toolchains:all")
+    native.register_toolchains("@local_jdk//:runtime_toolchain_definition")
+    for name in REMOTE_JDK_REPOS:
+        native.register_toolchains("@" + name + "_toolchain_config_repo//:toolchain")
diff --git a/renovate.json b/renovate.json
new file mode 100644
index 0000000..ee8c906
--- /dev/null
+++ b/renovate.json
@@ -0,0 +1,5 @@
+{
+    "extends": [
+        "config:base"
+    ]
+}
diff --git a/toolchains/BUILD b/toolchains/BUILD
new file mode 100644
index 0000000..b8cb35d
--- /dev/null
+++ b/toolchains/BUILD
@@ -0,0 +1,317 @@
+load("@rules_cc//cc:defs.bzl", "cc_library")
+load(
+    ":default_java_toolchain.bzl",
+    "DEFAULT_TOOLCHAIN_CONFIGURATION",
+    "PREBUILT_TOOLCHAIN_CONFIGURATION",
+    "bootclasspath",
+    "default_java_toolchain",
+    "java_runtime_files",
+)
+load(
+    ":java_toolchain_alias.bzl",
+    "java_host_runtime_alias",
+    "java_runtime_alias",
+    "java_runtime_version_alias",
+    "java_toolchain_alias",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+filegroup(
+    name = "srcs",
+    srcs = glob(["**"]),
+)
+
+filegroup(
+    name = "bzl_srcs",
+    srcs = glob(["*.bzl"]),
+)
+
+# Used to distinguish toolchains used for Java development, ie the JavaToolchainProvider.
+# TODO: migrate away from using @bazel_tools//tools/jdk:toolchain_type ?
+# toolchain_type(name = "toolchain_type")
+
+# Used to distinguish toolchains used for Java execution, ie the JavaRuntimeInfo.
+# TODO: migrate away from using @bazel_tools//tools/jdk:runtime_toolchain_type ?
+# toolchain_type(name = "runtime_toolchain_type")
+
+# Points to toolchain[":runtime_toolchain_type"] (was :legacy_current_java_runtime)
+java_runtime_alias(name = "current_java_runtime")
+
+# Host configuration of ":current_java_runtime"
+java_host_runtime_alias(name = "current_host_java_runtime")
+
+# Points to toolchain[":toolchain_type"] (was :legacy_current_java_toolchain)
+java_toolchain_alias(name = "current_java_toolchain")
+
+# These individual jni_* targets are exposed for legacy reasons.
+# Most users should depend on :jni.
+
+java_runtime_files(
+    name = "jni_header",
+    srcs = ["include/jni.h"],
+)
+
+java_runtime_files(
+    name = "jni_md_header-darwin",
+    srcs = ["include/darwin/jni_md.h"],
+)
+
+java_runtime_files(
+    name = "jni_md_header-linux",
+    srcs = ["include/linux/jni_md.h"],
+)
+
+java_runtime_files(
+    name = "jni_md_header-windows",
+    srcs = ["include/win32/jni_md.h"],
+)
+
+java_runtime_files(
+    name = "jni_md_header-freebsd",
+    srcs = ["include/freebsd/jni_md.h"],
+)
+
+java_runtime_files(
+    name = "jni_md_header-openbsd",
+    srcs = ["include/openbsd/jni_md.h"],
+)
+
+# The Java native interface. Depend on this package if you #include <jni.h>.
+#
+# See test_jni in third_party/bazel/src/test/shell/bazel/bazel_java_test.sh for
+# an example of using Bazel to build a Java program that calls a C function.
+#
+# TODO(ilist): use //src:condition:linux when released in Bazel
+cc_library(
+    name = "jni",
+    hdrs = [":jni_header"] + select({
+        "@bazel_tools//src/conditions:darwin": [":jni_md_header-darwin"],
+        "@bazel_tools//src/conditions:freebsd": [":jni_md_header-freebsd"],
+        "@bazel_tools//src/conditions:linux_aarch64": [":jni_md_header-linux"],
+        "@bazel_tools//src/conditions:linux_mips64": [":jni_md_header-linux"],
+        "@bazel_tools//src/conditions:linux_ppc64le": [":jni_md_header-linux"],
+        "@bazel_tools//src/conditions:linux_riscv64": [":jni_md_header-linux"],
+        "@bazel_tools//src/conditions:linux_s390x": [":jni_md_header-linux"],
+        "@bazel_tools//src/conditions:linux_x86_64": [":jni_md_header-linux"],
+        "@bazel_tools//src/conditions:openbsd": [":jni_md_header-openbsd"],
+        "@bazel_tools//src/conditions:windows": [":jni_md_header-windows"],
+        "//conditions:default": [],
+    }),
+    includes = ["include"] + select({
+        "@bazel_tools//src/conditions:darwin": ["include/darwin"],
+        "@bazel_tools//src/conditions:freebsd": ["include/freebsd"],
+        "@bazel_tools//src/conditions:linux_aarch64": ["include/linux"],
+        "@bazel_tools//src/conditions:linux_mips64": [":include/linux"],
+        "@bazel_tools//src/conditions:linux_ppc64le": ["include/linux"],
+        "@bazel_tools//src/conditions:linux_riscv64": [":include/linux"],
+        "@bazel_tools//src/conditions:linux_s390x": ["include/linux"],
+        "@bazel_tools//src/conditions:linux_x86_64": ["include/linux"],
+        "@bazel_tools//src/conditions:openbsd": ["include/openbsd"],
+        "@bazel_tools//src/conditions:windows": ["include/win32"],
+        "//conditions:default": [],
+    }),
+    tags = ["nobuilder"],
+)
+
+[
+    (
+        alias(
+            name = "ijar_prebuilt_binary_%s" % OS,
+            actual = "@remote_java_tools_%s//:ijar_prebuilt_binary" % OS,
+            visibility = ["//visibility:private"],
+        ),
+        alias(
+            name = "prebuilt_singlejar_%s" % OS,
+            actual = "@remote_java_tools_%s//:prebuilt_singlejar" % OS,
+            visibility = ["//visibility:private"],
+        ),
+    )
+    for OS in [
+        "linux",
+        "darwin_x86_64",
+        "darwin_arm64",
+        "windows",
+    ]
+]
+
+# On Windows, executables end in ".exe", but the label we reach it through
+# must be platform-independent. Thus, we create a little filegroup that
+# contains the appropriate platform-dependent file.
+alias(
+    name = "ijar",
+    actual = ":ijar_prebuilt_binary_or_cc_binary",
+)
+
+alias(
+    name = "ijar_prebuilt_binary_or_cc_binary",
+    actual = select({
+        "@bazel_tools//src/conditions:darwin_arm64": ":ijar_prebuilt_binary_darwin_arm64",
+        "@bazel_tools//src/conditions:darwin_x86_64": ":ijar_prebuilt_binary_darwin_x86_64",
+        "@bazel_tools//src/conditions:linux_x86_64": ":ijar_prebuilt_binary_linux",
+        "@bazel_tools//src/conditions:windows": ":ijar_prebuilt_binary_windows",
+        "//conditions:default": "@remote_java_tools//:ijar_cc_binary",
+    }),
+)
+
+alias(
+    name = "ijar_prebuilt_binary",
+    actual = select({
+        "@bazel_tools//src/conditions:darwin_arm64": ":ijar_prebuilt_binary_darwin_arm64",
+        "@bazel_tools//src/conditions:darwin_x86_64": ":ijar_prebuilt_binary_darwin_x86_64",
+        "@bazel_tools//src/conditions:linux_x86_64": ":ijar_prebuilt_binary_linux",
+        "@bazel_tools//src/conditions:windows": ":ijar_prebuilt_binary_windows",
+    }),
+)
+
+# On Windows, Java implementation of singlejar is used. We create a little
+# filegroup that contains the appropriate platform-dependent file.
+# Once https://github.com/bazelbuild/bazel/issues/2241 is fixed (that is,
+# the native singlejar is used on windows), this file group can be reused since
+# on Windows, executables end in ".exe", but the label we reach it through
+# must be platform-independent.
+alias(
+    name = "singlejar",
+    actual = ":singlejar_prebuilt_or_cc_binary",
+)
+
+alias(
+    name = "singlejar_prebuilt_or_cc_binary",
+    actual = select({
+        "@bazel_tools//src/conditions:darwin_arm64": ":prebuilt_singlejar_darwin_arm64",
+        "@bazel_tools//src/conditions:darwin_x86_64": ":prebuilt_singlejar_darwin_x86_64",
+        "@bazel_tools//src/conditions:linux_x86_64": ":prebuilt_singlejar_linux",
+        "@bazel_tools//src/conditions:windows": ":prebuilt_singlejar_windows",
+        "//conditions:default": "@remote_java_tools//:singlejar_cc_bin",
+    }),
+)
+
+alias(
+    name = "prebuilt_singlejar",
+    actual = select({
+        "@bazel_tools//src/conditions:darwin_arm64": ":prebuilt_singlejar_darwin_arm64",
+        "@bazel_tools//src/conditions:darwin_x86_64": ":prebuilt_singlejar_darwin_x86_64",
+        "@bazel_tools//src/conditions:linux_x86_64": ":prebuilt_singlejar_linux",
+        "@bazel_tools//src/conditions:windows": ":prebuilt_singlejar_windows",
+    }),
+)
+
+bootclasspath(
+    name = "platformclasspath",
+    src = "DumpPlatformClassPath.java",
+    host_javabase = ":current_java_runtime",
+    target_javabase = ":current_java_runtime",
+)
+
+default_java_toolchain(
+    name = "toolchain",
+    configuration = DEFAULT_TOOLCHAIN_CONFIGURATION,
+    toolchain_definition = False,
+)
+
+alias(
+    name = "remote_toolchain",
+    actual = ":toolchain",
+)
+
+RELEASES = (8, 9, 10, 11)
+
+[
+    default_java_toolchain(
+        name = "toolchain_java%d" % release,
+        configuration = DEFAULT_TOOLCHAIN_CONFIGURATION,
+        source_version = "%s" % release,
+        target_version = "%s" % release,
+    )
+    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",
+    configuration = dict(),
+    java_runtime = "//toolchains:remotejdk_15",
+    source_version = "15",
+    target_version = "15",
+)
+
+# A toolchain that targets java 16.
+default_java_toolchain(
+    name = "toolchain_jdk_16",
+    configuration = dict(),
+    java_runtime = "//toolchains:remotejdk_16",
+    source_version = "16",
+    target_version = "16",
+)
+
+# A toolchain that targets java 17.
+default_java_toolchain(
+    name = "toolchain_jdk_17",
+    configuration = dict(),
+    java_runtime = "//toolchains:remotejdk_17",
+    source_version = "17",
+    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,
+    toolchain_definition = False,
+)
+
+# A JDK 11 for use as a --host_javabase.
+java_runtime_version_alias(
+    name = "remote_jdk11",
+    runtime_version = "remotejdk_11",
+    visibility = ["//visibility:public"],
+)
+
+java_runtime_version_alias(
+    name = "remotejdk_15",
+    runtime_version = "remotejdk_15",
+    visibility = ["//visibility:public"],
+)
+
+java_runtime_version_alias(
+    name = "remotejdk_16",
+    runtime_version = "remotejdk_16",
+    visibility = ["//visibility:public"],
+)
+
+java_runtime_version_alias(
+    name = "remotejdk_17",
+    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/DumpPlatformClassPath.java b/toolchains/DumpPlatformClassPath.java
new file mode 100644
index 0000000..0832853
--- /dev/null
+++ b/toolchains/DumpPlatformClassPath.java
@@ -0,0 +1,269 @@
+// Copyright 2017 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.
+
+import com.sun.tools.javac.api.JavacTool;
+import com.sun.tools.javac.util.Context;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+
+/**
+ * Output a jar file containing all classes on the platform classpath of the given JDK release.
+ *
+ * <p>usage: DumpPlatformClassPath <release version> <output jar> <path to target JDK>?
+ */
+public class DumpPlatformClassPath {
+
+  public static void main(String[] args) throws Exception {
+    if (args.length != 2) {
+      System.err.println("usage: DumpPlatformClassPath <output jar> <path to target JDK>");
+      System.exit(1);
+    }
+    Path output = Paths.get(args[0]);
+    Path targetJavabase = Paths.get(args[1]);
+
+    int hostMajorVersion = hostMajorVersion();
+    boolean ok;
+    if (hostMajorVersion == 8) {
+      ok = dumpJDK8BootClassPath(output, targetJavabase);
+    } else {
+      ok = dumpJDK9AndNewerBootClassPath(hostMajorVersion, output, targetJavabase);
+    }
+    System.exit(ok ? 0 : 1);
+  }
+
+  // JDK 8 bootclasspath handling.
+  // * JDK 8 represents a bootclasspath as a search path of jars (rt.jar, etc.).
+  // * It does not support --release or --system.
+  static boolean dumpJDK8BootClassPath(Path output, Path targetJavabase) throws IOException {
+    List<Path> bootClassPathJars = getBootClassPathJars(targetJavabase);
+    writeClassPathJars(output, bootClassPathJars);
+    return true;
+  }
+
+  // JDK > 8 --host_javabase bootclasspath handling.
+  // (The default --host_javabase is currently JDK 9.)
+  static boolean dumpJDK9AndNewerBootClassPath(
+      int hostMajorVersion, Path output, Path targetJavabase) throws IOException {
+
+    // JDK 9 and newer support cross-compiling to older platform versions using the --system
+    // and --release flags.
+    // * --system takes the path to a JDK root for JDK 9 and up, and causes the compilation
+    //     to target the APIs from that JDK.
+    // * --release takes a language level (e.g. '9') and uses the API information baked in to
+    //     the host JDK (in lib/ct.sym).
+
+    // Since --system only supports JDK >= 9, first check of the target JDK defines a JDK 8
+    // bootclasspath.
+    List<Path> bootClassPathJars = getBootClassPathJars(targetJavabase);
+    if (!bootClassPathJars.isEmpty()) {
+      writeClassPathJars(output, bootClassPathJars);
+      return true;
+    }
+
+    // Initialize a FileManager to process the --system argument, and then read the
+    // initialized bootclasspath data back out.
+
+    Context context = new Context();
+    try {
+      JavacTool.create()
+          .getTask(
+              /* out = */ null,
+              /* fileManager = */ null,
+              /* diagnosticListener = */ null,
+              /* options = */ Arrays.asList("--system", String.valueOf(targetJavabase)),
+              /* classes = */ null,
+              /* compilationUnits = */ null,
+              context);
+    } catch (IllegalArgumentException e) {
+      throw new IllegalArgumentException(
+          String.format(
+              "Failed to collect system class path. Please ensure that the configured Java runtime"
+                  + " ('%s') is a complete JDK. There are known issues with Homebrew versions of"
+                  + " the Java runtime.",
+              targetJavabase.toRealPath()),
+          e);
+    }
+    StandardJavaFileManager fileManager =
+        (StandardJavaFileManager) context.get(JavaFileManager.class);
+
+    SortedMap<String, InputStream> entries = new TreeMap<>();
+    for (JavaFileObject fileObject :
+        fileManager.list(
+            StandardLocation.PLATFORM_CLASS_PATH,
+            "",
+            EnumSet.of(Kind.CLASS),
+            /* recurse= */ true)) {
+      String binaryName =
+          fileManager.inferBinaryName(StandardLocation.PLATFORM_CLASS_PATH, fileObject);
+      entries.put(binaryName.replace('.', '/') + ".class", fileObject.openInputStream());
+    }
+    writeEntries(output, entries);
+    return true;
+  }
+
+  /** Writes the given entry names and data to a jar archive at the given path. */
+  private static void writeEntries(Path output, Map<String, InputStream> entries)
+      throws IOException {
+    if (!entries.containsKey("java/lang/Object.class")) {
+      throw new AssertionError(
+          "\nCould not find java.lang.Object on bootclasspath; something has gone terribly wrong.\n"
+              + "Please file a bug: https://github.com/bazelbuild/bazel/issues");
+    }
+    try (OutputStream os = Files.newOutputStream(output);
+        BufferedOutputStream bos = new BufferedOutputStream(os, 65536);
+        JarOutputStream jos = new JarOutputStream(bos)) {
+      entries.entrySet().stream()
+          .forEachOrdered(
+              entry -> {
+                try {
+                  addEntry(jos, entry.getKey(), entry.getValue());
+                } catch (IOException e) {
+                  throw new UncheckedIOException(e);
+                }
+              });
+    }
+  }
+
+  /** Collects the entries of the given jar files into a map from jar entry names to their data. */
+  private static void writeClassPathJars(Path output, Collection<Path> paths) throws IOException {
+    List<JarFile> jars = new ArrayList<>();
+    for (Path path : paths) {
+      jars.add(new JarFile(path.toFile()));
+    }
+    SortedMap<String, InputStream> entries = new TreeMap<>();
+    for (JarFile jar : jars) {
+      jar.stream()
+          .filter(p -> p.getName().endsWith(".class"))
+          .forEachOrdered(
+              entry -> {
+                try {
+                  entries.put(entry.getName(), jar.getInputStream(entry));
+                } catch (IOException e) {
+                  throw new UncheckedIOException(e);
+                }
+              });
+    }
+    writeEntries(output, entries);
+    for (JarFile jar : jars) {
+      jar.close();
+    }
+  }
+
+  /** Returns paths to the entries of a JDK 8-style bootclasspath. */
+  private static List<Path> getBootClassPathJars(Path javaHome) throws IOException {
+    List<Path> jars = new ArrayList<>();
+    Path extDir = javaHome.resolve("jre/lib/ext");
+    if (Files.exists(extDir)) {
+      for (Path extJar : Files.newDirectoryStream(extDir, "*.jar")) {
+        jars.add(extJar);
+      }
+    }
+    for (String jar :
+        Arrays.asList("rt.jar", "resources.jar", "jsse.jar", "jce.jar", "charsets.jar")) {
+      Path path = javaHome.resolve("jre/lib").resolve(jar);
+      if (Files.exists(path)) {
+        jars.add(path);
+      }
+    }
+    return jars;
+  }
+
+  // Use a fixed timestamp for deterministic jar output.
+  private static final long FIXED_TIMESTAMP =
+      new GregorianCalendar(2010, 0, 1, 0, 0, 0).getTimeInMillis();
+
+  /**
+   * Add a jar entry to the given {@link JarOutputStream}, normalizing the entry timestamps to
+   * ensure deterministic build output.
+   */
+  private static void addEntry(JarOutputStream jos, String name, InputStream input)
+      throws IOException {
+    JarEntry je = new JarEntry(name);
+    je.setTime(FIXED_TIMESTAMP);
+    je.setMethod(ZipEntry.STORED);
+    byte[] bytes = toByteArray(input);
+    // When targeting JDK >= 10, patch the major version so it will be accepted by javac 9
+    // TODO(cushon): remove this after updating javac
+    if (bytes[7] > 53) {
+      bytes[7] = 53;
+    }
+    je.setSize(bytes.length);
+    CRC32 crc = new CRC32();
+    crc.update(bytes);
+    je.setCrc(crc.getValue());
+    jos.putNextEntry(je);
+    jos.write(bytes);
+  }
+
+  private static byte[] toByteArray(InputStream is) throws IOException {
+    byte[] buffer = new byte[8192];
+    ByteArrayOutputStream boas = new ByteArrayOutputStream();
+    while (true) {
+      int r = is.read(buffer);
+      if (r == -1) {
+        break;
+      }
+      boas.write(buffer, 0, r);
+    }
+    return boas.toByteArray();
+  }
+
+  /**
+   * Returns the major version of the host Java runtime (e.g. '8' for JDK 8), using {@link
+   * Runtime#version} if it is available, and otherwise falling back to the {@code
+   * java.class.version} system. property.
+   */
+  static int hostMajorVersion() {
+    try {
+      Method versionMethod = Runtime.class.getMethod("version");
+      Object version = versionMethod.invoke(null);
+      return (int) version.getClass().getMethod("major").invoke(version);
+    } catch (ReflectiveOperationException e) {
+      // Runtime.version() isn't available on JDK 8; continue below
+    }
+    int version = (int) Double.parseDouble(System.getProperty("java.class.version"));
+    if (49 <= version && version <= 52) {
+      return version - (49 - 5);
+    }
+    throw new IllegalStateException(
+        "Unknown Java version: " + System.getProperty("java.specification.version"));
+  }
+}
diff --git a/toolchains/default_java_toolchain.bzl b/toolchains/default_java_toolchain.bzl
new file mode 100644
index 0000000..9442c5e
--- /dev/null
+++ b/toolchains/default_java_toolchain.bzl
@@ -0,0 +1,289 @@
+# Copyright 2022 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.
+
+"""Rules for defining default_java_toolchain"""
+
+load("//java:defs.bzl", "java_toolchain")
+
+# JVM options, without patching java.compiler and jdk.compiler modules.
+BASE_JDK9_JVM_OPTS = [
+    # Allow JavaBuilder to access internal javac APIs.
+    "--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
+    "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
+    "--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
+    "--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED",
+    "--add-exports=jdk.compiler/com.sun.tools.javac.resources=ALL-UNNAMED",
+    "--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+    "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+    "--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
+    "--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
+    "--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
+    "--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
+
+    # quiet warnings from com.google.protobuf.UnsafeUtil,
+    # see: https://github.com/google/protobuf/issues/3781
+    # and: https://github.com/bazelbuild/bazel/issues/5599
+    "--add-opens=java.base/java.nio=ALL-UNNAMED",
+    "--add-opens=java.base/java.lang=ALL-UNNAMED",
+
+    # TODO(b/64485048): Disable this option in persistent worker mode only.
+    # Disable symlinks resolution cache since symlinks in exec root change
+    "-Dsun.io.useCanonCaches=false",
+
+    # 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
+
+DEFAULT_JAVACOPTS = [
+    "-XDskipDuplicateBridges=true",
+    "-XDcompilePolicy=simple",
+    "-g",
+    "-parameters",
+    # https://github.com/bazelbuild/bazel/issues/15219
+    "-Xep:ReturnValueIgnored:OFF",
+    # https://github.com/bazelbuild/bazel/issues/16996
+    "-Xep:IgnoredPureGetter:OFF",
+    "-Xep:EmptyTopLevelDeclaration:OFF",
+    "-Xep:LenientFormatStringValidation:OFF",
+    "-Xep:ReturnMissingNullable:OFF",
+]
+
+# Default java_toolchain parameters
+_BASE_TOOLCHAIN_CONFIGURATION = dict(
+    forcibly_disable_header_compilation = False,
+    genclass = [Label("@remote_java_tools//:GenClass")],
+    header_compiler = [Label("@remote_java_tools//:TurbineDirect")],
+    header_compiler_direct = [Label("@remote_java_tools//:TurbineDirect")],
+    ijar = [Label("//toolchains:ijar")],
+    javabuilder = [Label("@remote_java_tools//:JavaBuilder")],
+    javac_supports_workers = True,
+    jacocorunner = Label("@remote_java_tools//:jacoco_coverage_runner_filegroup"),
+    jvm_opts = BASE_JDK9_JVM_OPTS,
+    turbine_jvm_opts = [
+        # Turbine is not a worker and parallel GC is faster for short-lived programs.
+        "-XX:+UseParallelGC",
+    ],
+    misc = DEFAULT_JAVACOPTS,
+    singlejar = [Label("//toolchains:singlejar")],
+    # Code to enumerate target JVM boot classpath uses host JVM. Because
+    # java_runtime-s are involved, its implementation is in @bazel_tools.
+    bootclasspath = [Label("//toolchains:platformclasspath")],
+    source_version = "8",
+    target_version = "8",
+    reduced_classpath_incompatible_processors = [
+        "dagger.hilt.processor.internal.root.RootProcessor",  # see b/21307381
+    ],
+    java_runtime = Label("//toolchains:remotejdk_17"),
+)
+
+DEFAULT_TOOLCHAIN_CONFIGURATION = _BASE_TOOLCHAIN_CONFIGURATION
+
+# The 'vanilla' toolchain is an unsupported alternative to the default.
+#
+# It does not provide any of the following features:
+#   * Error Prone
+#   * Strict Java Deps
+#   * Reduced Classpath Optimization
+#
+# It uses the version of internal javac from the `--host_javabase` JDK instead
+# of providing a javac. Internal javac may not be source- or bug-compatible with
+# the javac that is provided with other toolchains.
+#
+# However it does allow using a wider range of `--host_javabase`s, including
+# versions newer than the current JDK.
+VANILLA_TOOLCHAIN_CONFIGURATION = dict(
+    javabuilder = [Label("@remote_java_tools//:VanillaJavaBuilder")],
+    jvm_opts = [],
+    java_runtime = None,
+)
+
+# The new toolchain is using all the pre-built tools, including
+# singlejar and ijar, even on remote execution. This toolchain
+# should be used only when host and execution platform are the
+# same, otherwise the binaries will not work on the execution
+# platform.
+PREBUILT_TOOLCHAIN_CONFIGURATION = dict(
+    ijar = [Label("//toolchains:ijar_prebuilt_binary")],
+    singlejar = [Label("//toolchains:prebuilt_singlejar")],
+)
+
+# The new toolchain is using all the tools from sources.
+NONPREBUILT_TOOLCHAIN_CONFIGURATION = dict(
+    ijar = [Label("@remote_java_tools//:ijar_cc_binary")],
+    singlejar = [Label("@remote_java_tools//:singlejar_cc_bin")],
+)
+
+_DEFAULT_SOURCE_VERSION = "8"
+
+def default_java_toolchain(name, configuration = DEFAULT_TOOLCHAIN_CONFIGURATION, toolchain_definition = True, exec_compatible_with = [], target_compatible_with = [], **kwargs):
+    """Defines a remote java_toolchain with appropriate defaults for Bazel.
+
+    Args:
+        name: The name of the toolchain
+        configuration: Toolchain configuration
+        toolchain_definition: Whether to define toolchain target and its config setting
+        exec_compatible_with: A list of constraint values that must be
+            satisifed for the exec platform.
+        target_compatible_with: A list of constraint values that must be
+            satisifed for the target platform.
+        **kwargs: More arguments for the java_toolchain target
+    """
+
+    toolchain_args = dict(_BASE_TOOLCHAIN_CONFIGURATION)
+    toolchain_args.update(configuration)
+    toolchain_args.update(kwargs)
+    java_toolchain(
+        name = name,
+        **toolchain_args
+    )
+    if toolchain_definition:
+        source_version = toolchain_args["source_version"]
+        if source_version == _DEFAULT_SOURCE_VERSION:
+            native.config_setting(
+                name = name + "_default_version_setting",
+                values = {"java_language_version": ""},
+                visibility = ["//visibility:private"],
+            )
+            native.toolchain(
+                name = name + "_default_definition",
+                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(
+            name = name + "_version_setting",
+            values = {"java_language_version": source_version},
+            visibility = ["//visibility:private"],
+        )
+        native.toolchain(
+            name = name + "_definition",
+            toolchain_type = Label("@bazel_tools//tools/jdk:toolchain_type"),
+            target_settings = [name + "_version_setting"],
+            toolchain = name,
+            exec_compatible_with = exec_compatible_with,
+            target_compatible_with = target_compatible_with,
+        )
+
+def java_runtime_files(name, srcs):
+    """Copies the given sources out of the current Java runtime."""
+
+    native.filegroup(
+        name = name,
+        srcs = srcs,
+        tags = ["manual"],
+    )
+    for src in srcs:
+        native.genrule(
+            name = "gen_%s" % src,
+            srcs = [Label("//toolchains:current_java_runtime")],
+            toolchains = [Label("//toolchains:current_java_runtime")],
+            cmd = "cp $(JAVABASE)/%s $@" % src,
+            outs = [src],
+            tags = ["manual"],
+        )
+
+def _bootclasspath_impl(ctx):
+    host_javabase = ctx.attr.host_javabase[java_common.JavaRuntimeInfo]
+
+    class_dir = ctx.actions.declare_directory("%s_classes" % ctx.label.name)
+
+    args = ctx.actions.args()
+    args.add("-source")
+    args.add("8")
+    args.add("-target")
+    args.add("8")
+    args.add("-Xlint:-options")
+    args.add("-d")
+    args.add_all([class_dir], expand_directories = False)
+    args.add(ctx.file.src)
+
+    ctx.actions.run(
+        executable = "%s/bin/javac" % host_javabase.java_home,
+        mnemonic = "JavaToolchainCompileClasses",
+        inputs = [ctx.file.src] + ctx.files.host_javabase,
+        outputs = [class_dir],
+        arguments = [args],
+    )
+
+    bootclasspath = ctx.outputs.output_jar
+
+    inputs = [class_dir] + ctx.files.host_javabase
+
+    args = ctx.actions.args()
+    args.add("-XX:+IgnoreUnrecognizedVMOptions")
+    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_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)
+
+    ctx.actions.run(
+        executable = str(host_javabase.java_executable_exec_path),
+        mnemonic = "JavaToolchainCompileBootClasspath",
+        inputs = inputs,
+        outputs = [bootclasspath],
+        arguments = [args],
+    )
+    return [
+        DefaultInfo(files = depset([bootclasspath])),
+        java_common.BootClassPathInfo(
+            bootclasspath = [bootclasspath],
+            system = system,
+        ),
+        OutputGroupInfo(jar = [bootclasspath]),
+    ]
+
+_bootclasspath = rule(
+    implementation = _bootclasspath_impl,
+    attrs = {
+        "host_javabase": attr.label(
+            cfg = "exec",
+            providers = [java_common.JavaRuntimeInfo],
+        ),
+        "output_jar": attr.output(mandatory = True),
+        "src": attr.label(
+            cfg = "exec",
+            allow_single_file = True,
+        ),
+        "target_javabase": attr.label(
+            providers = [java_common.JavaRuntimeInfo],
+        ),
+    },
+)
+
+def bootclasspath(name, **kwargs):
+    _bootclasspath(
+        name = name,
+        output_jar = name + ".jar",
+        **kwargs
+    )
diff --git a/toolchains/fail_rule.bzl b/toolchains/fail_rule.bzl
new file mode 100644
index 0000000..a8a3da2
--- /dev/null
+++ b/toolchains/fail_rule.bzl
@@ -0,0 +1,35 @@
+# Copyright 2020 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 rule than fails during analysis."""
+
+def _fail_rule_impl(ctx):
+    if ctx.attr.header:
+        fail("%s %s" % (ctx.attr.header, ctx.attr.message))
+    else:
+        fail(ctx.attr.message)
+
+fail_rule = rule(
+    doc = "A rule that fails during analysis.",
+    implementation = _fail_rule_impl,
+    attrs = {
+        "header": attr.string(
+            doc = "Header of the message.",
+        ),
+        "message": attr.string(
+            mandatory = True,
+            doc = "Message to display.",
+        ),
+    },
+)
diff --git a/toolchains/java_toolchain_alias.bzl b/toolchains/java_toolchain_alias.bzl
new file mode 100644
index 0000000..21fae7e
--- /dev/null
+++ b/toolchains/java_toolchain_alias.bzl
@@ -0,0 +1,114 @@
+# 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.
+
+"""Experimental re-implementations of Java toolchain aliases using toolchain resolution."""
+
+def _java_runtime_alias(ctx):
+    """An experimental implementation of java_runtime_alias using toolchain resolution."""
+    toolchain_info = ctx.toolchains["@bazel_tools//tools/jdk:runtime_toolchain_type"]
+    toolchain = toolchain_info.java_runtime
+    return [
+        toolchain_info,
+        toolchain,
+        platform_common.TemplateVariableInfo({
+            "JAVA": str(toolchain.java_executable_exec_path),
+            "JAVABASE": str(toolchain.java_home),
+        }),
+        # See b/65239471 for related discussion of handling toolchain runfiles/data.
+        DefaultInfo(
+            runfiles = ctx.runfiles(transitive_files = toolchain.files),
+            files = toolchain.files,
+        ),
+    ]
+
+java_runtime_alias = rule(
+    implementation = _java_runtime_alias,
+    toolchains = ["@bazel_tools//tools/jdk:runtime_toolchain_type"],
+    incompatible_use_toolchain_transition = True,
+)
+
+def _java_host_runtime_alias(ctx):
+    """An experimental implementation of java_host_runtime_alias using toolchain resolution."""
+    runtime = ctx.attr._runtime
+    java_runtime = runtime[java_common.JavaRuntimeInfo]
+    template_variable_info = runtime[platform_common.TemplateVariableInfo]
+    toolchain_info = platform_common.ToolchainInfo(java_runtime = java_runtime)
+    return [
+        java_runtime,
+        template_variable_info,
+        toolchain_info,
+        runtime[DefaultInfo],
+    ]
+
+java_host_runtime_alias = rule(
+    implementation = _java_host_runtime_alias,
+    attrs = {
+        "_runtime": attr.label(
+            default = Label("//toolchains:current_java_runtime"),
+            providers = [
+                java_common.JavaRuntimeInfo,
+                platform_common.TemplateVariableInfo,
+            ],
+            cfg = "exec",
+        ),
+    },
+    provides = [
+        java_common.JavaRuntimeInfo,
+        platform_common.TemplateVariableInfo,
+        platform_common.ToolchainInfo,
+    ],
+)
+
+def _java_runtime_transition_impl(_settings, attr):
+    return {"//command_line_option:java_runtime_version": attr.runtime_version}
+
+_java_runtime_transition = transition(
+    implementation = _java_runtime_transition_impl,
+    inputs = [],
+    outputs = ["//command_line_option:java_runtime_version"],
+)
+
+java_runtime_version_alias = rule(
+    implementation = _java_runtime_alias,
+    toolchains = ["@bazel_tools//tools/jdk:runtime_toolchain_type"],
+    incompatible_use_toolchain_transition = True,
+    attrs = {
+        "runtime_version": attr.string(mandatory = True),
+        "_allowlist_function_transition": attr.label(
+            default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
+        ),
+    },
+    cfg = _java_runtime_transition,
+)
+
+def _java_toolchain_alias(ctx):
+    """An experimental implementation of java_toolchain_alias using toolchain resolution."""
+    toolchain_info = ctx.toolchains["@bazel_tools//tools/jdk:toolchain_type"]
+    toolchain = toolchain_info.java
+
+    # buildifier: disable=rule-impl-return
+    return struct(
+        providers = [
+            toolchain_info,
+            toolchain,
+        ],
+        # Use the legacy provider syntax for compatibility with the native rules.
+        java_toolchain = toolchain,
+    )
+
+java_toolchain_alias = rule(
+    implementation = _java_toolchain_alias,
+    toolchains = ["@bazel_tools//tools/jdk:toolchain_type"],
+    incompatible_use_toolchain_transition = True,
+)
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
new file mode 100644
index 0000000..ab25f0d
--- /dev/null
+++ b/toolchains/local_java_repository.bzl
@@ -0,0 +1,283 @@
+# Copyright 2021 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.
+
+"""Rules for importing and registering a local JDK."""
+
+load("//java:defs.bzl", "java_runtime")
+load(":default_java_toolchain.bzl", "default_java_toolchain")
+
+def _detect_java_version(repository_ctx, java_bin):
+    properties_out = repository_ctx.execute([java_bin, "-XshowSettings:properties"]).stderr
+    # This returns an indented list of properties separated with newlines:
+    # "  java.vendor.url.bug = ... \n"
+    # "  java.version = 11.0.8\n"
+    # "  java.version.date = 2020-11-05\"
+
+    strip_properties = [property.strip() for property in properties_out.splitlines()]
+    version_property = [property for property in strip_properties if property.startswith("java.version = ")]
+    if len(version_property) != 1:
+        return None
+
+    version_value = version_property[0][len("java.version = "):]
+    parts = version_value.split(".")
+    major = parts[0]
+    if len(parts) == 1:
+        return major
+    elif major == "1":  # handles versions below 1.8
+        minor = parts[1]
+        return minor
+    return major
+
+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
+    value set to either name or version argument.
+
+    Java compile toolchains are created for --java_language_version flags values
+    between 8 and version (inclusive). Java compile toolchains use the same
+    (local) JDK for compilation. This requires a different configuration for JDK8
+    than the newer versions.
+
+    Args:
+      name: name of the target.
+      java_home: Path to the JDK.
+      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:
+        runtime_name = name
+        java_runtime(
+            name = runtime_name,
+            java_home = java_home,
+            visibility = visibility,
+            version = int(version) if version.isdigit() else 0,
+        )
+
+    native.config_setting(
+        name = name + "_name_setting",
+        values = {"java_runtime_version": name},
+        visibility = ["//visibility:private"],
+    )
+    native.config_setting(
+        name = name + "_version_setting",
+        values = {"java_runtime_version": version},
+        visibility = ["//visibility:private"],
+    )
+    native.config_setting(
+        name = name + "_name_version_setting",
+        values = {"java_runtime_version": name + "_" + version},
+        visibility = ["//visibility:private"],
+    )
+    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",
+        }),
+        visibility = ["//visibility:private"],
+    )
+    native.toolchain(
+        name = "runtime_toolchain_definition",
+        target_settings = [":%s_settings_alias" % name],
+        toolchain_type = Label("@bazel_tools//tools/jdk:runtime_toolchain_type"),
+        toolchain = runtime_name,
+    )
+
+    if type(version) == type("") and version.isdigit() and int(version) > 8:
+        for version in range(8, int(version) + 1):
+            default_java_toolchain(
+                name = name + "_toolchain_java" + str(version),
+                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
+
+def _is_macos(repository_ctx):
+    return repository_ctx.os.name.lower().find("mac os x") != -1
+
+def _is_windows(repository_ctx):
+    return repository_ctx.os.name.lower().find("windows") != -1
+
+def _with_os_extension(repository_ctx, binary):
+    return binary + (".exe" if _is_windows(repository_ctx) else "")
+
+def _determine_java_home(repository_ctx):
+    """Determine the java home path.
+
+    If the `java_home` attribute is specified, then use the given path,
+    otherwise, try to detect the java home path on the system.
+
+    Args:
+      repository_ctx: repository context
+    """
+    java_home = repository_ctx.attr.java_home
+    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)))
+        return java_home_path
+    if "JAVA_HOME" in repository_ctx.os.environ:
+        return repository_ctx.path(repository_ctx.os.environ["JAVA_HOME"])
+
+    if _is_macos(repository_ctx):
+        # Replicate GetSystemJavabase() in src/main/cpp/blaze_util_darwin.cc
+        result = repository_ctx.execute(["/usr/libexec/java_home", "-v", "1.11+"])
+        if result.return_code == 0:
+            return repository_ctx.path(result.stdout.strip())
+    else:
+        # Calculate java home by locating the javac binary
+        # javac should exists at ${JAVA_HOME}/bin/javac
+        # Replicate GetSystemJavabase() in src/main/cpp/blaze_util_linux.cc
+        # This logic should also work on Windows.
+        javac_path = repository_ctx.which(_with_os_extension(repository_ctx, "javac"))
+        if javac_path:
+            return javac_path.realpath.dirname.dirname
+    return repository_ctx.path("./nosystemjdk")
+
+def _local_java_repository_impl(repository_ctx):
+    """Repository rule local_java_repository implementation.
+
+    Args:
+      repository_ctx: repository context
+    """
+
+    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 = local_java_runtime_name),
+    )
+
+    java_bin = java_home.get_child("bin").get_child(_with_os_extension(repository_ctx, "java"))
+
+    if not java_bin.exists:
+        # Java binary does not exist
+        repository_ctx.file(
+            "BUILD.bazel",
+            _NOJDK_BUILD_TPL.format(
+                local_jdk = local_java_runtime_name,
+                java_binary = _with_os_extension(repository_ctx, "bin/java"),
+                java_home = java_home,
+            ),
+            False,
+        )
+        return
+
+    # Detect version
+    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
+    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 build_file else None
+    local_java_runtime_macro = """
+local_java_runtime(
+    name = "%s",
+    runtime_name = %s,
+    java_home = "%s",
+    version = "%s",
+)
+""" % (local_java_runtime_name, runtime_name, java_home, version)
+
+    repository_ctx.file(
+        "BUILD.bazel",
+        'load("@rules_java//toolchains:local_java_repository.bzl", "local_java_runtime")\n' +
+        build_file +
+        local_java_runtime_macro,
+    )
+
+    # Symlink all files
+    for file in repository_ctx.path(java_home).readdir():
+        repository_ctx.symlink(file, file.basename)
+
+# Build file template, when JDK does not exist
+_NOJDK_BUILD_TPL = '''load("@rules_java//toolchains:fail_rule.bzl", "fail_rule")
+fail_rule(
+   name = "jdk",
+   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)")
+)
+config_setting(
+   name = "localjdk_setting",
+   values = {{"java_runtime_version": "{local_jdk}"}},
+   visibility = ["//visibility:private"],
+)
+toolchain(
+   name = "runtime_toolchain_definition",
+   target_settings = [":localjdk_setting"],
+   toolchain_type = "@bazel_tools//tools/jdk:runtime_toolchain_type",
+   toolchain = ":jdk",
+)
+'''
+
+_local_java_repository_rule = repository_rule(
+    implementation = _local_java_repository_impl,
+    local = True,
+    configure = True,
+    environ = ["JAVA_HOME"],
+    attrs = {
+        "build_file": attr.label(),
+        "build_file_content": attr.string(),
+        "java_home": attr.string(),
+        "version": attr.string(),
+    },
+)
+
+def local_java_repository(name, java_home = "", version = "", build_file = None, build_file_content = None, **kwargs):
+    """Registers a runtime toolchain for local JDK and creates an unregistered compile toolchain.
+
+    Toolchain resolution is constrained with --java_runtime_version flag
+    having value of the "name" or "version" parameter.
+
+    Java compile toolchains are created for --java_language_version flags values
+    between 8 and version (inclusive). Java compile toolchains use the same
+    (local) JDK for compilation.
+
+    If there is no JDK "virtual" targets are created, which fail only when actually needed.
+
+    Args:
+      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
+      **kwargs: additional arguments for repository rule
+    """
+    _local_java_repository_rule(name = name, java_home = java_home, version = version, build_file = build_file, build_file_content = build_file_content, **kwargs)
diff --git a/toolchains/remote_java_repository.bzl b/toolchains/remote_java_repository.bzl
new file mode 100644
index 0000000..cbd8b13
--- /dev/null
+++ b/toolchains/remote_java_repository.bzl
@@ -0,0 +1,88 @@
+# Copyright 2020 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.
+
+"""Rules for importing and registering JDKs from http archive.
+
+Rule remote_java_repository imports and registers JDK with the toolchain resolution.
+"""
+
+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))
+    ctx.file("BUILD.bazel", ctx.attr.build_file)
+
+_toolchain_config = repository_rule(
+    local = True,
+    implementation = _toolchain_config_impl,
+    attrs = {
+        "build_file": attr.string(),
+    },
+)
+
+def remote_java_repository(name, version, target_compatible_with = None, prefix = "remotejdk", **kwargs):
+    """Imports and registers a JDK from a http archive.
+
+    Toolchain resolution is determined with target_compatible_with
+    parameter and constrained with --java_runtime_version flag either having value
+    of "version" or "{prefix}_{version}" parameters.
+
+    Args:
+      name: A unique name for this rule.
+      version: Version of the JDK imported.
+      target_compatible_with: Target platform constraints (CPU and OS) for this JDK.
+      prefix: Optional alternative prefix for configuration flag value used to determine this JDK.
+      **kwargs: Refer to http_archive documentation
+    """
+    http_archive(
+        name = name,
+        build_file_content = JDK_BUILD_TEMPLATE.format(RUNTIME_VERSION = version),
+        **kwargs
+    )
+    _toolchain_config(
+        name = name + "_toolchain_config_repo",
+        build_file = """
+config_setting(
+    name = "prefix_version_setting",
+    values = {{"java_runtime_version": "{prefix}_{version}"}},
+    visibility = ["//visibility:private"],
+)
+config_setting(
+    name = "version_setting",
+    values = {{"java_runtime_version": "{version}"}},
+    visibility = ["//visibility:private"],
+)
+alias(
+    name = "version_or_prefix_version_setting",
+    actual = select({{
+        ":version_setting": ":version_setting",
+        "//conditions:default": ":prefix_version_setting",
+    }}),
+    visibility = ["//visibility:private"],
+)
+toolchain(
+    name = "toolchain",
+    target_compatible_with = {target_compatible_with},
+    target_settings = [":version_or_prefix_version_setting"],
+    toolchain_type = "@bazel_tools//tools/jdk:runtime_toolchain_type",
+    toolchain = "{toolchain}",
+)
+""".format(
+            prefix = prefix,
+            version = version,
+            target_compatible_with = target_compatible_with,
+            toolchain = "@{repo}//:jdk".format(repo = name),
+        ),
+    )
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]