Copy over files from @bazel_tools//tools/jdk
diff --git a/toolchains/BUILD b/toolchains/BUILD
index 67d2c89..6f7fef4 100644
--- a/toolchains/BUILD
+++ b/toolchains/BUILD
@@ -1,3 +1,21 @@
+load(
+    "@bazel_tools//tools/jdk:default_java_toolchain.bzl",
+    "DEFAULT_TOOLCHAIN_CONFIGURATION",
+    "JVM8_TOOLCHAIN_CONFIGURATION",
+    "PREBUILT_TOOLCHAIN_CONFIGURATION",
+    "VANILLA_TOOLCHAIN_CONFIGURATION",
+    "bootclasspath",
+    "default_java_toolchain",
+    "java_runtime_files",
+)
+load(
+    "//tools/jdk: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"])
@@ -7,3 +25,490 @@
     srcs = glob(["**"]),
     visibility = ["@//:__pkg__"],
 )
+
+
+load("//tools/python:private/defs.bzl", "py_binary", "py_test")
+
+package(default_visibility = ["//visibility:public"])
+
+# Used to distinguish toolchains used for Java development, ie the JavaToolchainProvider.
+toolchain_type(name = "toolchain_type")
+
+# Used to distinguish toolchains used for Java execution, ie the JavaRuntimeInfo.
+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")
+
+# Aliases value of --plugins flag as a JavaPluginInfo
+java_plugins_flag_alias(
+    name = "java_plugins_flag_alias",
+)
+
+# This is necessary to get the *host* Java runtime. Depending on
+# //tools/jdk:current_java_runtime from an attribute with the host transition
+# does not work because the dependency is determined based on the configuration
+# *before* the transition.
+alias(
+    name = "java_runtime_alias",
+    actual = "//tools/jdk:current_java_runtime",
+)
+
+# 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({
+        "//src/conditions:linux_aarch64": [":jni_md_header-linux"],
+        "//src/conditions:linux_ppc64le": [":jni_md_header-linux"],
+        "//src/conditions:linux_s390x": [":jni_md_header-linux"],
+        "//src/conditions:linux_mips64": [":jni_md_header-linux"],
+        "//src/conditions:linux_riscv64": [":jni_md_header-linux"],
+        "//src/conditions:linux_x86_64": [":jni_md_header-linux"],
+        "//src/conditions:darwin": [":jni_md_header-darwin"],
+        "//src/conditions:freebsd": [":jni_md_header-freebsd"],
+        "//src/conditions:openbsd": [":jni_md_header-openbsd"],
+        "//src/conditions:windows": [":jni_md_header-windows"],
+        "//conditions:default": [],
+    }),
+    includes = ["include"] + select({
+        "//src/conditions:linux_aarch64": ["include/linux"],
+        "//src/conditions:linux_ppc64le": ["include/linux"],
+        "//src/conditions:linux_s390x": ["include/linux"],
+        "//src/conditions:linux_mips64": [":include/linux"],
+        "//src/conditions:linux_riscv64": [":include/linux"],
+        "//src/conditions:linux_x86_64": ["include/linux"],
+        "//src/conditions:darwin": ["include/darwin"],
+        "//src/conditions:freebsd": ["include/freebsd"],
+        "//src/conditions:openbsd": ["include/openbsd"],
+        "//src/conditions:windows": ["include/win32"],
+        "//conditions:default": [],
+    }),
+)
+
+alias(
+    name = "java",
+    actual = "@local_jdk//:java",
+)
+
+alias(
+    name = "jar",
+    actual = "@local_jdk//:jar",
+)
+
+alias(
+    name = "javac",
+    actual = "@local_jdk//:javac",
+)
+
+alias(
+    name = "javadoc",
+    actual = "@local_jdk//:javadoc",
+)
+
+[
+    (
+        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",
+        "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({
+        "//src/conditions:linux_x86_64": ":ijar_prebuilt_binary_linux",
+        "//src/conditions:darwin": ":ijar_prebuilt_binary_darwin",
+        "//src/conditions:windows": ":ijar_prebuilt_binary_windows",
+        "//conditions:default": "@remote_java_tools//:ijar_cc_binary",
+    }),
+)
+
+alias(
+    name = "ijar_prebuilt_binary",
+    actual = select({
+        "//src/conditions:linux_x86_64": ":ijar_prebuilt_binary_linux",
+        "//src/conditions:darwin": ":ijar_prebuilt_binary_darwin",
+        "//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({
+        "//src/conditions:linux_x86_64": ":prebuilt_singlejar_linux",
+        "//src/conditions:darwin": ":prebuilt_singlejar_darwin",
+        "//src/conditions:windows": ":prebuilt_singlejar_windows",
+        "//conditions:default": "@remote_java_tools//:singlejar_cc_bin",
+    }),
+)
+
+alias(
+    name = "prebuilt_singlejar",
+    actual = select({
+        "//src/conditions:linux_x86_64": ":prebuilt_singlejar_linux",
+        "//src/conditions:darwin": ":prebuilt_singlejar_darwin",
+        "//src/conditions:windows": ":prebuilt_singlejar_windows",
+    }),
+)
+
+exports_files(["BUILD.java_tools"])
+
+alias(
+    name = "genclass",
+    actual = "@remote_java_tools//:GenClass",
+)
+
+alias(
+    name = "GenClass_deploy.jar",
+    actual = "@remote_java_tools//:GenClass",
+)
+
+alias(
+    name = "turbine",
+    actual = "@remote_java_tools//:Turbine",
+)
+
+alias(
+    name = "turbine_deploy.jar",
+    actual = "@remote_java_tools//:Turbine",
+)
+
+alias(
+    name = "turbine_direct",
+    actual = "@remote_java_tools//:TurbineDirect",
+)
+
+alias(
+    name = "turbine_direct_binary_deploy.jar",
+    actual = "@remote_java_tools//:TurbineDirect",
+)
+
+alias(
+    name = "javabuilder",
+    actual = "@remote_java_tools//:JavaBuilder",
+)
+
+alias(
+    name = "JavaBuilder_deploy.jar",
+    actual = "@remote_java_tools//:JavaBuilder",
+)
+
+alias(
+    name = "vanillajavabuilder",
+    actual = "@remote_java_tools//:VanillaJavaBuilder",
+)
+
+alias(
+    name = "javac_jar",
+    actual = "@remote_java_tools//:javac_jar",
+)
+
+alias(
+    name = "jdk_compiler_jar",
+    actual = "@remote_java_tools//:jdk_compiler_jar",
+)
+
+alias(
+    name = "java_compiler_jar",
+    actual = "@remote_java_tools//:java_compiler_jar",
+)
+
+alias(
+    name = "JacocoCoverageRunner",
+    actual = "@remote_java_tools//:jacoco_coverage_runner",
+)
+
+alias(
+    name = "JacocoCoverage",
+    actual = "@remote_java_tools//:jacoco_coverage_runner",
+)
+
+java_import(
+    name = "TestRunner",
+    jars = ["@remote_java_tools//:Runner"],
+)
+
+alias(
+    name = "TestRunner_deploy.jar",
+    actual = "@remote_java_tools//:Runner",
+)
+
+alias(
+    name = "proguard",
+    actual = "@remote_java_tools//:proguard",
+)
+
+BOOTCLASS_JARS = [
+    "rt.jar",
+    "resources.jar",
+    "jsse.jar",
+    "jce.jar",
+    "charsets.jar",
+]
+
+# TODO(cushon): this isn't compatible with JDK 9
+alias(
+    name = "bootclasspath",
+    actual = "@local_jdk//:bootclasspath",
+)
+
+alias(
+    name = "jre",
+    actual = "@local_jdk//:jre",
+)
+
+alias(
+    name = "jdk",
+    actual = "@local_jdk//:jdk",
+)
+
+alias(
+    name = "host_jdk",
+    actual = ":remote_jdk11",
+)
+
+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 = "@bazel_tools//tools/jdk: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 = "@bazel_tools//tools/jdk: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 = "@bazel_tools//tools/jdk: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 = "@bazel_tools//tools/jdk:remotejdk_17",
+    source_version = "17",
+    target_version = "17",
+)
+
+# Deprecated, do not use.
+# It will be removed after migration to Java toolchain resolution.
+default_java_toolchain(
+    name = "toolchain_hostjdk8",
+    configuration = JVM8_TOOLCHAIN_CONFIGURATION,
+    java_runtime = ":current_host_java_runtime",
+    source_version = "8",
+    target_version = "8",
+    toolchain_definition = False,
+)
+
+default_java_toolchain(
+    name = "prebuilt_toolchain",
+    configuration = PREBUILT_TOOLCHAIN_CONFIGURATION,
+    toolchain_definition = False,
+)
+
+filegroup(
+    name = "bzl_srcs",
+    srcs = glob(["*.bzl"]),
+    visibility = ["//tools:__pkg__"],
+)
+
+py_binary(
+    name = "proguard_whitelister",
+    srcs = [
+        "proguard_whitelister.py",
+    ],
+    deps = [
+        "//third_party/py/abseil",
+    ],
+)
+
+py_test(
+    name = "proguard_whitelister_test",
+    srcs = ["proguard_whitelister_test.py"],
+    data = ["proguard_whitelister_test_input.pgcfg"],
+    deps = [
+        ":proguard_whitelister",
+    ],
+)
+
+# Aliases for JDKs, so that they are only downloaded when needed.
+_JDKS = [
+    "remotejdk11_macos",
+    "remotejdk11_macos_aarch64",
+    "remotejdk11_win",
+    "remotejdk11_linux_aarch64",
+    "remotejdk11_linux",
+    "remotejdk11_linux_ppc64le",
+    "remotejdk11_linux_s390x",
+    "remotejdk15_macos",
+    "remotejdk15_macos_aarch64",
+    "remotejdk15_win",
+    "remotejdk15_linux",
+    "remotejdk16_macos",
+    "remotejdk16_macos_aarch64",
+    "remotejdk16_win",
+    "remotejdk16_linux",
+    "remotejdk17_macos",
+    "remotejdk17_macos_aarch64",
+    "remotejdk17_win",
+    "remotejdk17_linux",
+]
+
+[
+    alias(
+        name = JDK,
+        actual = "@%s//:jdk" % JDK,
+        visibility = ["//visibility:private"],
+    )
+    for JDK in _JDKS
+]
+
+# 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 = "jdk_8",
+    runtime_version = "8",
+    visibility = ["//visibility:public"],
+)
diff --git a/toolchains/DumpPlatformClassPath.java b/toolchains/DumpPlatformClassPath.java
new file mode 100644
index 0000000..e23ca53
--- /dev/null
+++ b/toolchains/DumpPlatformClassPath.java
@@ -0,0 +1,259 @@
+// 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();
+    JavacTool.create()
+        .getTask(
+            /* out = */ null,
+            /* fileManager = */ null,
+            /* diagnosticListener = */ null,
+            /* options = */ Arrays.asList("--system", String.valueOf(targetJavabase)),
+            /* classes = */ null,
+            /* compilationUnits = */ null,
+            context);
+    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..ac8ed5d
--- /dev/null
+++ b/toolchains/default_java_toolchain.bzl
@@ -0,0 +1,293 @@
+# 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.
+
+"""Bazel rules for creating Java toolchains."""
+
+JDK8_JVM_OPTS = [
+    "-Xbootclasspath/p:$(location @remote_java_tools//:javac_jar)",
+]
+
+# 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.parser=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",
+
+    # 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",
+]
+
+JDK9_JVM_OPTS = BASE_JDK9_JVM_OPTS + [
+    # override the javac in the JDK.
+    "--patch-module=java.compiler=$(location @remote_java_tools//:java_compiler_jar)",
+    "--patch-module=jdk.compiler=$(location @remote_java_tools//:jdk_compiler_jar)",
+]
+
+DEFAULT_JAVACOPTS = [
+    "-XDskipDuplicateBridges=true",
+    "-XDcompilePolicy=simple",
+    "-g",
+    "-parameters",
+    # https://github.com/bazelbuild/java_tools/issues/51#issuecomment-927940699
+    "-XepOpt:ReturnValueIgnored:ObjectMethods=false",
+]
+
+# java_toolchain parameters without specifying javac, java.compiler,
+# jdk.compiler module, and jvm_opts
+_BASE_TOOLCHAIN_CONFIGURATION = dict(
+    forcibly_disable_header_compilation = False,
+    genclass = ["@remote_java_tools//:GenClass"],
+    header_compiler = ["@remote_java_tools//:TurbineDirect"],
+    header_compiler_direct = ["@remote_java_tools//:TurbineDirect"],
+    ijar = ["@bazel_tools//tools/jdk:ijar"],
+    javabuilder = ["@remote_java_tools//:JavaBuilder"],
+    javac_supports_workers = True,
+    jacocorunner = "@remote_java_tools//:jacoco_coverage_runner_filegroup",
+    jvm_opts = BASE_JDK9_JVM_OPTS,
+    misc = DEFAULT_JAVACOPTS,
+    singlejar = ["@bazel_tools//tools/jdk:singlejar"],
+    # Code to enumerate target JVM boot classpath uses host JVM. Because
+    # java_runtime-s are involved, its implementation is in @bazel_tools.
+    bootclasspath = ["@bazel_tools//tools/jdk:platformclasspath"],
+    source_version = "8",
+    target_version = "8",
+    reduced_classpath_incompatible_processors = [
+        "dagger.hilt.processor.internal.root.RootProcessor",  # see b/21307381
+    ],
+)
+
+JVM8_TOOLCHAIN_CONFIGURATION = dict(
+    tools = ["@remote_java_tools//:javac_jar"],
+    jvm_opts = ["-Xbootclasspath/p:$(location @remote_java_tools//:javac_jar)"],
+    java_runtime = "@bazel_tools//tools/jdk:jdk_8",
+)
+
+DEFAULT_TOOLCHAIN_CONFIGURATION = dict(
+    jvm_opts = [
+        # Compact strings make JavaBuilder slightly slower.
+        "-XX:-CompactStrings",
+    ] + JDK9_JVM_OPTS,
+    turbine_jvm_opts = [
+        # Turbine is not a worker and parallel GC is faster for short-lived programs.
+        "-XX:+UseParallelOldGC",
+    ],
+    tools = [
+        "@remote_java_tools//:java_compiler_jar",
+        "@remote_java_tools//:jdk_compiler_jar",
+    ],
+    java_runtime = "@bazel_tools//tools/jdk:remote_jdk11",
+)
+
+# 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 = ["@remote_java_tools//:VanillaJavaBuilder"],
+    jvm_opts = [],
+)
+
+# 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(
+    jvm_opts = [
+        # Compact strings make JavaBuilder slightly slower.
+        "-XX:-CompactStrings",
+    ] + JDK9_JVM_OPTS,
+    turbine_jvm_opts = [
+        # Turbine is not a worker and parallel GC is faster for short-lived programs.
+        "-XX:+UseParallelOldGC",
+    ],
+    tools = [
+        "@remote_java_tools//:java_compiler_jar",
+        "@remote_java_tools//:jdk_compiler_jar",
+    ],
+    ijar = ["@bazel_tools//tools/jdk:ijar_prebuilt_binary"],
+    singlejar = ["@bazel_tools//tools/jdk:prebuilt_singlejar"],
+    java_runtime = "@bazel_tools//tools/jdk:remote_jdk11",
+)
+
+# The new toolchain is using all the tools from sources.
+NONPREBUILT_TOOLCHAIN_CONFIGURATION = dict(
+    jvm_opts = [
+        # Compact strings make JavaBuilder slightly slower.
+        "-XX:-CompactStrings",
+    ] + JDK9_JVM_OPTS,
+    turbine_jvm_opts = [
+        # Turbine is not a worker and parallel GC is faster for short-lived programs.
+        "-XX:+UseParallelOldGC",
+    ],
+    tools = [
+        "@remote_java_tools//:java_compiler_jar",
+        "@remote_java_tools//:jdk_compiler_jar",
+    ],
+    ijar = ["@remote_java_tools//:ijar_cc_binary"],
+    singlejar = ["@remote_java_tools//:singlejar_cc_bin"],
+    java_runtime = "@bazel_tools//tools/jdk:remote_jdk11",
+)
+
+def default_java_toolchain(name, configuration = DEFAULT_TOOLCHAIN_CONFIGURATION, toolchain_definition = True, **kwargs):
+    """Defines a remote java_toolchain with appropriate defaults for Bazel."""
+
+    toolchain_args = dict(_BASE_TOOLCHAIN_CONFIGURATION)
+    toolchain_args.update(configuration)
+    toolchain_args.update(kwargs)
+    native.java_toolchain(
+        name = name,
+        **toolchain_args
+    )
+    if toolchain_definition:
+        native.config_setting(
+            name = name + "_version_setting",
+            values = {"java_language_version": toolchain_args["source_version"]},
+            visibility = ["//visibility:private"],
+        )
+        native.toolchain(
+            name = name + "_definition",
+            toolchain_type = "@bazel_tools//tools/jdk:toolchain_type",
+            target_settings = [name + "_version_setting"],
+            toolchain = name,
+        )
+
+def java_runtime_files(name, srcs):
+    """Copies the given sources out of the current Java runtime."""
+
+    native.filegroup(
+        name = name,
+        srcs = srcs,
+    )
+    for src in srcs:
+        native.genrule(
+            name = "gen_%s" % src,
+            srcs = ["@bazel_tools//tools/jdk:current_java_runtime"],
+            toolchains = ["@bazel_tools//tools/jdk:current_java_runtime"],
+            cmd = "cp $(JAVABASE)/%s $@" % src,
+            outs = [src],
+        )
+
+def _bootclasspath_impl(ctx):
+    host_javabase = ctx.attr.host_javabase[java_common.JavaRuntimeInfo]
+
+    # explicitly list output files instead of using TreeArtifact to work around
+    # https://github.com/bazelbuild/bazel/issues/6203
+    classes = [
+        "DumpPlatformClassPath.class",
+    ]
+
+    class_outputs = [
+        ctx.actions.declare_file("%s_classes/%s" % (ctx.label.name, clazz))
+        for clazz in classes
+    ]
+
+    args = ctx.actions.args()
+    args.add("-source")
+    args.add("8")
+    args.add("-target")
+    args.add("8")
+    args.add("-Xlint:-options")
+    args.add("-cp")
+    args.add("%s/lib/tools.jar" % host_javabase.java_home)
+    args.add("-d")
+    args.add(class_outputs[0].dirname)
+    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_outputs,
+        arguments = [args],
+    )
+
+    bootclasspath = ctx.outputs.output_jar
+
+    inputs = class_outputs + 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_joined(
+        "-cp",
+        [class_outputs[0].dirname, "%s/lib/tools.jar" % host_javabase.java_home],
+        join_with = ctx.configuration.host_path_separator,
+    )
+    args.add("DumpPlatformClassPath")
+    args.add(bootclasspath)
+
+    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])),
+        OutputGroupInfo(jar = [bootclasspath]),
+    ]
+
+_bootclasspath = rule(
+    implementation = _bootclasspath_impl,
+    attrs = {
+        "host_javabase": attr.label(
+            cfg = "host",
+            providers = [java_common.JavaRuntimeInfo],
+        ),
+        "src": attr.label(
+            cfg = "host",
+            allow_single_file = True,
+        ),
+        "target_javabase": attr.label(
+            providers = [java_common.JavaRuntimeInfo],
+        ),
+        "output_jar": attr.output(mandatory = True),
+    },
+)
+
+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..ddf6d3f
--- /dev/null
+++ b/toolchains/java_toolchain_alias.bzl
@@ -0,0 +1,112 @@
+# 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("@bazel_tools//tools/jdk:current_java_runtime"),
+            providers = [
+                java_common.JavaRuntimeInfo,
+                platform_common.TemplateVariableInfo,
+            ],
+            cfg = "host",
+        ),
+    },
+    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
+    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 b/toolchains/jdk.BUILD
new file mode 100644
index 0000000..6870771
--- /dev/null
+++ b/toolchains/jdk.BUILD
@@ -0,0 +1,218 @@
+load("@rules_java//java:defs.bzl", "java_import", "java_runtime")
+
+package(default_visibility = ["//visibility:public"])
+
+exports_files(["BUILD.bazel"])
+
+DEPRECATION_MESSAGE = ("Don't depend on targets in the JDK workspace;" +
+                       " use @bazel_tools//tools/jdk:current_java_runtime instead" +
+                       " (see https://github.com/bazelbuild/bazel/issues/5594)")
+
+filegroup(
+    name = "jni_header",
+    srcs = ["include/jni.h"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "jni_md_header-darwin",
+    srcs = ["include/darwin/jni_md.h"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "jni_md_header-linux",
+    srcs = ["include/linux/jni_md.h"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "jni_md_header-freebsd",
+    srcs = ["include/freebsd/jni_md.h"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "jni_md_header-openbsd",
+    srcs = ["include/openbsd/jni_md.h"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "jni_md_header-windows",
+    srcs = ["include/win32/jni_md.h"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "java",
+    srcs = select({
+        ":windows": ["bin/java.exe"],
+        "//conditions:default": ["bin/java"],
+    }),
+    data = [":jdk"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "jar",
+    srcs = select({
+        ":windows": ["bin/jar.exe"],
+        "//conditions:default": ["bin/jar"],
+    }),
+    data = [":jdk"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "javac",
+    srcs = select({
+        ":windows": ["bin/javac.exe"],
+        "//conditions:default": ["bin/javac"],
+    }),
+    data = [":jdk"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "javadoc",
+    srcs = select({
+        ":windows": ["bin/javadoc.exe"],
+        "//conditions:default": ["bin/javadoc"],
+    }),
+    data = [":jdk"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "xjc",
+    srcs = ["bin/xjc"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "wsimport",
+    srcs = ["bin/wsimport"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+BOOTCLASS_JARS = [
+    "rt.jar",
+    "resources.jar",
+    "jsse.jar",
+    "jce.jar",
+    "charsets.jar",
+]
+
+# TODO(cushon): this isn't compatible with JDK 9
+filegroup(
+    name = "bootclasspath",
+    srcs = ["jre/lib/%s" % jar for jar in BOOTCLASS_JARS],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "jre-bin",
+    srcs = select({
+        # In some configurations, Java browser plugin is considered harmful and
+        # common antivirus software blocks access to npjp2.dll interfering with Bazel,
+        # so do not include it in JRE on Windows.
+        ":windows": glob(
+            ["jre/bin/**"],
+            allow_empty = True,
+            exclude = ["jre/bin/plugin2/**"],
+        ),
+        "//conditions:default": glob(
+            ["jre/bin/**"],
+            allow_empty = True,
+        ),
+    }),
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "jre-lib",
+    srcs = glob(
+        ["jre/lib/**"],
+        allow_empty = True,
+    ),
+)
+
+filegroup(
+    name = "jre",
+    srcs = [":jre-default"],
+)
+
+filegroup(
+    name = "jre-default",
+    srcs = [
+        ":jre-bin",
+        ":jre-lib",
+    ],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+filegroup(
+    name = "jdk-bin",
+    srcs = glob(
+        ["bin/**"],
+        # The JDK on Windows sometimes contains a directory called
+        # "%systemroot%", which is not a valid label.
+        exclude = ["**/*%*/**"],
+    ),
+)
+
+#This folder holds security policies
+filegroup(
+    name = "jdk-conf",
+    srcs = glob(
+        ["conf/**"],
+        allow_empty = True,
+    ),
+)
+
+filegroup(
+    name = "jdk-include",
+    srcs = glob(["include/**"]),
+)
+
+filegroup(
+    name = "jdk-lib",
+    srcs = glob(
+        ["lib/**"],
+        exclude = [
+            "lib/missioncontrol/**",
+            "lib/visualvm/**",
+        ],
+    ),
+)
+
+java_runtime(
+    name = "jdk",
+    srcs = [
+        ":jdk-bin",
+        ":jdk-conf",
+        ":jdk-include",
+        ":jdk-lib",
+        ":jre-default",
+    ],
+)
+
+filegroup(
+    name = "langtools",
+    srcs = ["lib/tools.jar"],
+    deprecation = DEPRECATION_MESSAGE,
+)
+
+java_import(
+    name = "langtools-neverlink",
+    deprecation = DEPRECATION_MESSAGE,
+    jars = ["lib/tools.jar"],
+    neverlink = 1,
+)
+
+config_setting(
+    name = "windows",
+    values = {"cpu": "x64_windows"},
+    visibility = ["//visibility:private"],
+)
diff --git a/toolchains/local_java_repository.bzl b/toolchains/local_java_repository.bzl
new file mode 100644
index 0000000..4c0a433
--- /dev/null
+++ b/toolchains/local_java_repository.bzl
@@ -0,0 +1,232 @@
+# 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 a local JDK."""
+
+load(":default_java_toolchain.bzl", "JVM8_TOOLCHAIN_CONFIGURATION", "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"]):
+    """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
+    """
+    if runtime_name == None:
+        runtime_name = name
+        native.java_runtime(
+            name = runtime_name,
+            java_home = java_home,
+            visibility = visibility,
+        )
+
+    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 = "@bazel_tools//tools/jdk:runtime_toolchain_type",
+        toolchain = runtime_name,
+    )
+
+    if version == "8":
+        default_java_toolchain(
+            name = name + "_toolchain_java8",
+            configuration = JVM8_TOOLCHAIN_CONFIGURATION,
+            source_version = version,
+            target_version = version,
+            java_runtime = runtime_name,
+        )
+    elif 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,
+            )
+
+    # else version is not recognized and no compilation toolchains are predefined
+
+def _local_java_repository_impl(repository_ctx):
+    """Repository rule local_java_repository implementation.
+
+    Args:
+      repository_ctx: repository context
+    """
+    java_home = repository_ctx.attr.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)))
+
+    repository_ctx.file(
+        "WORKSPACE",
+        "# DO NOT EDIT: automatically generated WORKSPACE file for local_java_repository\n" +
+        "workspace(name = \"{name}\")\n".format(name = repository_ctx.name),
+    )
+
+    extension = ".exe" if repository_ctx.os.name.lower().find("windows") != -1 else ""
+    java_bin = java_home_path.get_child("bin").get_child("java" + extension)
+
+    if not java_bin.exists:
+        # Java binary does not exist
+        repository_ctx.file(
+            "BUILD.bazel",
+            _NOJDK_BUILD_TPL.format(
+                local_jdk = repository_ctx.name,
+                java_binary = "bin/java" + extension,
+                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
+    build_file = ""
+    if repository_ctx.attr.build_file != None:
+        build_file = repository_ctx.read(repository_ctx.path(repository_ctx.attr.build_file))
+
+    runtime_name = '"jdk"' if repository_ctx.attr.build_file else None
+    local_java_runtime_macro = """
+local_java_runtime(
+    name = "%s",
+    runtime_name = %s,
+    java_home = "%s",
+    version = "%s",
+)
+""" % (repository_ctx.name, runtime_name, java_home, version)
+
+    repository_ctx.file(
+        "BUILD.bazel",
+        'load("@bazel_tools//tools/jdk: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("@bazel_tools//tools/jdk: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,
+    attrs = {
+        "java_home": attr.string(),
+        "version": attr.string(),
+        "build_file": attr.label(),
+    },
+)
+
+def local_java_repository(name, java_home, version = "", build_file = None):
+    """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
+      version: optionally java version
+    """
+    _local_java_repository_rule(name = name, java_home = java_home, version = version, build_file = build_file)
+    native.register_toolchains("@" + name + "//:runtime_toolchain_definition")