Pass `ct.sym` to direct version of Turbine

This ensures that Turbine has access to `ct.sym` and thus supports the `--release` flag even if it is compiled into a Graal native image, which doesn't have access to a `JAVA_HOME`.

This requires exposing the `ct.sym` file on a new `lib_ct_sym` attribute of `java_runtime` and passing it into Turbine via the `turbine.ctSymPath` system property introduced in v0.3.1.

Along the way this commit fixes the setup code for testing unreleased versions of the remote Java and coverage tools, which silently broke with the flip of `--enable_bzlmod`.

Work towards https://github.com/bazelbuild/stardoc/issues/195

Closes #20294.

PiperOrigin-RevId: 585866870
Change-Id: I416b787e324bd3a01e223edbda4f9ba137c21241
diff --git a/MODULE.bazel b/MODULE.bazel
index e925eed..c650e1e 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -95,7 +95,7 @@
         "com.google.http-client:google-http-client-gson:1.42.0",
         "com.google.http-client:google-http-client:1.42.0",
         "com.google.j2objc:j2objc-annotations:1.3",
-        "com.google.turbine:turbine:0.3.0",
+        "com.google.turbine:turbine:0.3.1",
         "com.ryanharter.auto.value:auto-value-gson-extension:1.3.1",
         "com.ryanharter.auto.value:auto-value-gson-runtime:1.3.1",
         "com.ryanharter.auto.value:auto-value-gson-factory:1.3.1",
diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock
index a5fd825..6cfbdd5 100644
--- a/MODULE.bazel.lock
+++ b/MODULE.bazel.lock
@@ -1,6 +1,6 @@
 {
   "lockFileVersion": 3,
-  "moduleFileHash": "b14b53947e8576ba68f334eee96d4901cbceaf1c77ca3cd8339ae266a08f6329",
+  "moduleFileHash": "efe69027e004cac2bb887c4bbb4ebf3b7c081978db5a6fe4063a53c95ba3470f",
   "flags": {
     "cmdRegistries": [
       "https://bcr.bazel.build/"
@@ -84,7 +84,7 @@
                   "com.google.http-client:google-http-client-gson:1.42.0",
                   "com.google.http-client:google-http-client:1.42.0",
                   "com.google.j2objc:j2objc-annotations:1.3",
-                  "com.google.turbine:turbine:0.3.0",
+                  "com.google.turbine:turbine:0.3.1",
                   "com.ryanharter.auto.value:auto-value-gson-extension:1.3.1",
                   "com.ryanharter.auto.value:auto-value-gson-runtime:1.3.1",
                   "com.ryanharter.auto.value:auto-value-gson-factory:1.3.1",
@@ -2249,7 +2249,7 @@
         "bzlTransitiveDigest": "/h6B2Wl9PVY+Bv0PAxzkZUmm947eWCyYthDYT5CPX+k=",
         "accumulatedFileDigests": {
           "@@//src/test/tools/bzlmod:MODULE.bazel.lock": "e7caa4d6182abd31642ac06dfc30a4501a998924fbd68b59eced1e1cf836da5f",
-          "@@//:MODULE.bazel": "b14b53947e8576ba68f334eee96d4901cbceaf1c77ca3cd8339ae266a08f6329"
+          "@@//:MODULE.bazel": "efe69027e004cac2bb887c4bbb4ebf3b7c081978db5a6fe4063a53c95ba3470f"
         },
         "envVariables": {},
         "generatedRepoSpecs": {
@@ -4342,7 +4342,7 @@
       "general": {
         "bzlTransitiveDigest": "WAWsskOl4eHIskcL0TuHZGIMjV8sMJaAbAo2luMqofo=",
         "accumulatedFileDigests": {
-          "@@//:maven_install.json": "b259897b96e082526f660bf5b48542cc0ba9f5d42d1bc5eee1ca3c3bd60a20b8",
+          "@@//:maven_install.json": "1fdc15fe77e07e3f272d16db3b7000ce575e4f534306b4b4f0dbe61a473d2bb3",
           "@@rules_jvm_external~5.2//:rules_jvm_external_deps_install.json": "3ab1f67b0de4815df110bc72ccd6c77882b3b21d3d1e0a84445847b6ce3235a3",
           "@@//src/tools/android:maven_android_install.json": "09bff3e33d291336046f7c9201630fb5e014f0e60b78b6f09b84e4f5f73ed04f"
         },
@@ -4876,7 +4876,7 @@
                 "{ \"group\": \"com.google.http-client\", \"artifact\": \"google-http-client-gson\", \"version\": \"1.42.0\" }",
                 "{ \"group\": \"com.google.http-client\", \"artifact\": \"google-http-client\", \"version\": \"1.42.0\" }",
                 "{ \"group\": \"com.google.j2objc\", \"artifact\": \"j2objc-annotations\", \"version\": \"1.3\" }",
-                "{ \"group\": \"com.google.turbine\", \"artifact\": \"turbine\", \"version\": \"0.3.0\" }",
+                "{ \"group\": \"com.google.turbine\", \"artifact\": \"turbine\", \"version\": \"0.3.1\" }",
                 "{ \"group\": \"com.ryanharter.auto.value\", \"artifact\": \"auto-value-gson-extension\", \"version\": \"1.3.1\" }",
                 "{ \"group\": \"com.ryanharter.auto.value\", \"artifact\": \"auto-value-gson-runtime\", \"version\": \"1.3.1\" }",
                 "{ \"group\": \"com.ryanharter.auto.value\", \"artifact\": \"auto-value-gson-factory\", \"version\": \"1.3.1\" }",
@@ -7399,7 +7399,7 @@
                 "{ \"group\": \"com.google.http-client\", \"artifact\": \"google-http-client-gson\", \"version\": \"1.42.0\" }",
                 "{ \"group\": \"com.google.http-client\", \"artifact\": \"google-http-client\", \"version\": \"1.42.0\" }",
                 "{ \"group\": \"com.google.j2objc\", \"artifact\": \"j2objc-annotations\", \"version\": \"1.3\" }",
-                "{ \"group\": \"com.google.turbine\", \"artifact\": \"turbine\", \"version\": \"0.3.0\" }",
+                "{ \"group\": \"com.google.turbine\", \"artifact\": \"turbine\", \"version\": \"0.3.1\" }",
                 "{ \"group\": \"com.ryanharter.auto.value\", \"artifact\": \"auto-value-gson-extension\", \"version\": \"1.3.1\" }",
                 "{ \"group\": \"com.ryanharter.auto.value\", \"artifact\": \"auto-value-gson-runtime\", \"version\": \"1.3.1\" }",
                 "{ \"group\": \"com.ryanharter.auto.value\", \"artifact\": \"auto-value-gson-factory\", \"version\": \"1.3.1\" }",
@@ -8010,6 +8010,18 @@
               "downloaded_file_path": "org/yaml/snakeyaml/1.28/snakeyaml-1.28.jar"
             }
           },
+          "com_google_turbine_turbine_0_3_1": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_file",
+            "attributes": {
+              "name": "rules_jvm_external~5.2~maven~com_google_turbine_turbine_0_3_1",
+              "sha256": "c0778917005294a59c805a60a5ace2ec847dcece41ced70680f675d822fc03a7",
+              "urls": [
+                "https://repo1.maven.org/maven2/com/google/turbine/turbine/0.3.1/turbine-0.3.1.jar"
+              ],
+              "downloaded_file_path": "com/google/turbine/turbine/0.3.1/turbine-0.3.1.jar"
+            }
+          },
           "io_netty_netty_transport_native_epoll_jar_linux_aarch_64_4_1_93_Final": {
             "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
             "ruleClassName": "http_file",
@@ -8035,18 +8047,6 @@
               "downloaded_file_path": "com/android/tools/build/aapt2-proto/7.0.0-beta04-7396180/aapt2-proto-7.0.0-beta04-7396180.jar"
             }
           },
-          "com_google_turbine_turbine_0_3_0": {
-            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
-            "ruleClassName": "http_file",
-            "attributes": {
-              "name": "rules_jvm_external~5.2~maven~com_google_turbine_turbine_0_3_0",
-              "sha256": "3fee92239ec300ef4142e2e32ac81af3123cce9cdc552ca78429086ed8c5a445",
-              "urls": [
-                "https://repo1.maven.org/maven2/com/google/turbine/turbine/0.3.0/turbine-0.3.0.jar"
-              ],
-              "downloaded_file_path": "com/google/turbine/turbine/0.3.0/turbine-0.3.0.jar"
-            }
-          },
           "com_google_protobuf_protobuf_java_3_13_0": {
             "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
             "ruleClassName": "http_file",
diff --git a/maven_install.json b/maven_install.json
index 7c56caf..fcad3f5 100644
--- a/maven_install.json
+++ b/maven_install.json
@@ -1,7 +1,7 @@
 {
   "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
-  "__INPUT_ARTIFACTS_HASH": -922870577,
-  "__RESOLVED_ARTIFACTS_HASH": 1291237234,
+  "__INPUT_ARTIFACTS_HASH": 143984014,
+  "__RESOLVED_ARTIFACTS_HASH": -866086153,
   "conflict_resolution": {
     "com.google.code.gson:gson:2.8.9": "com.google.code.gson:gson:2.9.0",
     "com.google.errorprone:error_prone_annotations:2.3.2": "com.google.errorprone:error_prone_annotations:2.23.0",
@@ -278,9 +278,9 @@
     },
     "com.google.turbine:turbine": {
       "shasums": {
-        "jar": "3fee92239ec300ef4142e2e32ac81af3123cce9cdc552ca78429086ed8c5a445"
+        "jar": "c0778917005294a59c805a60a5ace2ec847dcece41ced70680f675d822fc03a7"
       },
-      "version": "0.3.0"
+      "version": "0.3.1"
     },
     "com.ryanharter.auto.value:auto-value-gson-extension": {
       "shasums": {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeRule.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeRule.java
index 33cc59c..533c180 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeRule.java
@@ -51,6 +51,16 @@
         Files in the runtime needed for hermetic deployments.
         <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
         .add(attr("hermetic_srcs", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE))
+        /* <!-- #BLAZE_RULE(java_runtime).ATTRIBUTE(lib_ct_sym) -->
+        The lib/ct.sym file needed for compilation with <code>--release</code>. If not specified and
+        there is exactly one file in <code>srcs</code> whose path ends with
+        <code>/lib/ct.sym</code>, that file is used.
+        <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+        .add(
+            attr("lib_ct_sym", LABEL)
+                .singleArtifact()
+                .allowedFileTypes(FileTypeSet.ANY_FILE)
+                .exec())
         /* <!-- #BLAZE_RULE(java_runtime).ATTRIBUTE(lib_modules) -->
         The lib/modules file needed for hermetic deployments.
         <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainTool.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainTool.java
index d756f8c..027b3f9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainTool.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainTool.java
@@ -64,8 +64,8 @@
   public abstract NestedSet<Artifact> data();
 
   /**
-   * JVM flags to invoke the tool with, or empty if it is not a {@code _deploy.jar}. Location
-   * expansion is performed on these flags using the inputs in {@link #data}.
+   * JVM flags to invoke the tool with. Location expansion is performed on these flags using the
+   * inputs in {@link #data}.
    */
   public abstract NestedSet<String> jvmOpts();
 
@@ -105,7 +105,7 @@
 
     Artifact executable = tool().getExecutable();
     if (!executable.getExtension().equals("jar")) {
-      command.addExecPath(executable);
+      command = command.addExecPath(executable).addAll(jvmOpts());
     } else {
       command
           .addPath(toolchain.getJavaRuntime().javaBinaryExecPathFragment())
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaRuntimeInfoApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaRuntimeInfoApi.java
index 0b7a321..296746b 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaRuntimeInfoApi.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaRuntimeInfoApi.java
@@ -80,6 +80,15 @@
       structField = true)
   Depset starlarkHermeticInputs();
 
+  /** The lib/ct.sym file. */
+  @StarlarkMethod(
+      name = "lib_ct_sym",
+      doc = "Returns the lib/ct.sym file.",
+      structField = true,
+      allowReturnNones = true)
+  @Nullable
+  FileApi libCtSym();
+
   /** The lib/modules file. */
   @StarlarkMethod(
       name = "lib_modules",
diff --git a/src/main/starlark/builtins_bzl/common/java/java_runtime.bzl b/src/main/starlark/builtins_bzl/common/java/java_runtime.bzl
index 96cb03c..781a453 100644
--- a/src/main/starlark/builtins_bzl/common/java/java_runtime.bzl
+++ b/src/main/starlark/builtins_bzl/common/java/java_runtime.bzl
@@ -45,6 +45,7 @@
                 This should only be used when one needs to access the JDK during the execution
                 of a binary or a test built by Bazel. In particular, when one needs the JDK
                 during an action, java_home should be used instead.""",
+        "lib_ct_sym": "Returns the lib/ct.sym file.",
         "lib_modules": "Returns the lib/modules file.",
         "version": "The Java feature version of the runtime. This is 0 if the version is unknown.",
     },
@@ -75,6 +76,15 @@
 def _is_java_binary(path):
     return path.endswith("bin/java") or path.endswith("bin/java.exe")
 
+def _get_lib_ct_sym(srcs, explicit_lib_ct_sym):
+    if explicit_lib_ct_sym:
+        return explicit_lib_ct_sym
+    candidates = [src for src in srcs if src.path.endswith("/lib/ct.sym")]
+    if len(candidates) == 1:
+        return candidates[0]
+    else:
+        return None
+
 def _java_runtime_rule_impl(ctx):
     all_files = []  # [depset[File]]
     all_files.append(depset(ctx.files.srcs))
@@ -105,6 +115,7 @@
     hermetic_inputs = depset(ctx.files.hermetic_srcs)
     all_files.append(hermetic_inputs)
 
+    lib_ct_sym = _get_lib_ct_sym(ctx.files.srcs, ctx.file.lib_ct_sym)
     lib_modules = ctx.file.lib_modules
     hermetic_static_libs = [dep[CcInfo] for dep in ctx.attr.hermetic_static_libs]
 
@@ -128,6 +139,7 @@
         java_executable_runfiles_path = java_binary_runfiles_path,
         java_home = java_home,
         java_home_runfiles_path = java_home_runfiles_path,
+        lib_ct_sym = lib_ct_sym,
         lib_modules = lib_modules,
         version = ctx.attr.version,
     )
@@ -152,6 +164,7 @@
         "hermetic_static_libs": attr.label_list(providers = [CcInfo]),
         "java": attr.label(allow_single_file = True, executable = True, cfg = "target"),
         "java_home": attr.string(),
+        "lib_ct_sym": attr.label(allow_single_file = True),
         "lib_modules": attr.label(allow_single_file = True, executable = True, cfg = "target"),
         "output_licenses": attr.license() if hasattr(attr, "license") else attr.string_list(),
         "srcs": attr.label_list(allow_files = True),
diff --git a/src/main/starlark/builtins_bzl/common/java/java_toolchain.bzl b/src/main/starlark/builtins_bzl/common/java/java_toolchain.bzl
index 726bbf5..3d80ad1 100644
--- a/src/main/starlark/builtins_bzl/common/java/java_toolchain.bzl
+++ b/src/main/starlark/builtins_bzl/common/java/java_toolchain.bzl
@@ -78,11 +78,18 @@
 def _java_toolchain_impl(ctx):
     javac_opts_list = _get_javac_opts(ctx)
     bootclasspath_info = _get_bootclasspath_info(ctx)
+    java_runtime = _get_java_runtime(ctx)
+    if java_runtime and java_runtime.lib_ct_sym:
+        header_compiler_direct_data = [java_runtime.lib_ct_sym]
+        header_compiler_direct_jvm_opts = ["-Dturbine.ctSymPath=" + java_runtime.lib_ct_sym.path]
+    else:
+        header_compiler_direct_data = []
+        header_compiler_direct_jvm_opts = []
     java_toolchain_info = _new_javatoolchaininfo(
         bootclasspath = bootclasspath_info.bootclasspath,
         ijar = ctx.attr.ijar.files_to_run if ctx.attr.ijar else None,
         jacocorunner = ctx.attr.jacocorunner.files_to_run if ctx.attr.jacocorunner else None,
-        java_runtime = _get_java_runtime(ctx),
+        java_runtime = java_runtime,
         jvm_opt = depset(_java_common_internal.expand_java_opts(ctx, "jvm_opts", tokenize = False, exec_paths = True)),
         label = ctx.label,
         proguard_allowlister = ctx.attr.proguard_allowlister.files_to_run if ctx.attr.proguard_allowlister else None,
@@ -100,7 +107,12 @@
         _gen_class = ctx.file.genclass,
         _header_compiler = _get_tool_from_ctx(ctx, "header_compiler", "turbine_data", "turbine_jvm_opts"),
         _header_compiler_builtin_processors = depset(ctx.attr.header_compiler_builtin_processors),
-        _header_compiler_direct = _get_tool_from_executable(ctx, "header_compiler_direct"),
+        _header_compiler_direct = _get_tool_from_executable(
+            ctx,
+            "header_compiler_direct",
+            data = header_compiler_direct_data,
+            jvm_opts = header_compiler_direct_jvm_opts,
+        ),
         _javabuilder = _get_tool_from_ctx(ctx, "javabuilder", "javabuilder_data", "javabuilder_jvm_opts"),
         _javacopts = helper.detokenize_javacopts(javac_opts_list),
         _javacopts_list = javac_opts_list,
@@ -174,14 +186,14 @@
         jvm_opts = depset([ctx.expand_location(opt, data) for opt in getattr(ctx.attr, opts_attr)]),
     )
 
-def _get_tool_from_executable(ctx, attr_name):
+def _get_tool_from_executable(ctx, attr_name, data = [], jvm_opts = []):
     dep = getattr(ctx.attr, attr_name)
     if not dep:
         return None
     files_to_run = dep.files_to_run
     if not files_to_run or not files_to_run.executable:
         fail(dep.label, "does not refer to a valid executable target")
-    return struct(tool = files_to_run, data = depset(), jvm_opts = depset())
+    return struct(tool = files_to_run, data = depset(data), jvm_opts = depset(jvm_opts))
 
 def _get_compatible_javacopts(ctx):
     result = {}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/java/JavaStarlarkApiTest.java b/src/test/java/com/google/devtools/build/lib/rules/java/JavaStarlarkApiTest.java
index 13e06c5..5ab33f1 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/java/JavaStarlarkApiTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/java/JavaStarlarkApiTest.java
@@ -3567,6 +3567,97 @@
   }
 
   @Test
+  public void implicitLibCtSym() throws Exception {
+    scratch.file("a/libStatic.a");
+    scratch.file(
+        "a/BUILD",
+        "load(':rule.bzl', 'jrule')",
+        "load('"
+            + TestConstants.TOOLS_REPOSITORY
+            + "//tools/jdk:java_toolchain_alias.bzl', 'java_runtime_alias')",
+        "java_runtime(",
+        "    name='jvm',",
+        "    srcs=[",
+        "        'foo/bar/bin/java',",
+        "        'foo/bar/lib/ct.sym',",
+        "    ],",
+        "    java='foo/bar/bin/java',",
+        ")",
+        "java_runtime_alias(name='alias')",
+        "jrule(name='r')",
+        "toolchain(",
+        "    name = 'java_runtime_toolchain',",
+        "    toolchain = ':jvm',",
+        "    toolchain_type = '"
+            + TestConstants.TOOLS_REPOSITORY
+            + "//tools/jdk:runtime_toolchain_type',",
+        ")");
+    scratch.file(
+        "a/rule.bzl",
+        "load('//myinfo:myinfo.bzl', 'MyInfo')",
+        "def _impl(ctx):",
+        "  provider = ctx.attr._java_runtime[java_common.JavaRuntimeInfo]",
+        "  return MyInfo(",
+        "    lib_ct_sym = provider.lib_ct_sym,",
+        "  )",
+        "jrule = rule(_impl, attrs = { '_java_runtime': attr.label(default=Label('//a:alias'))})");
+
+    useConfiguration("--extra_toolchains=//a:all");
+    ConfiguredTarget ct = getConfiguredTarget("//a:r");
+    StructImpl myInfo = getMyInfoFromTarget(ct);
+    @SuppressWarnings("unchecked")
+    Artifact libCtSym = (Artifact) myInfo.getValue("lib_ct_sym");
+    assertThat(libCtSym).isNotNull();
+    assertThat(libCtSym.getExecPathString()).isEqualTo("a/foo/bar/lib/ct.sym");
+  }
+
+  @Test
+  public void explicitLibCtSym() throws Exception {
+    scratch.file("a/libStatic.a");
+    scratch.file(
+        "a/BUILD",
+        "load(':rule.bzl', 'jrule')",
+        "load('"
+            + TestConstants.TOOLS_REPOSITORY
+            + "//tools/jdk:java_toolchain_alias.bzl', 'java_runtime_alias')",
+        "java_runtime(",
+        "    name='jvm',",
+        "    srcs=[",
+        "        'foo/bar/bin/java',",
+        "        'foo/bar/lib/ct.sym',",
+        "    ],",
+        "    java='foo/bar/bin/java',",
+        "    lib_ct_sym='lib/ct.sym',",
+        ")",
+        "java_runtime_alias(name='alias')",
+        "jrule(name='r')",
+        "toolchain(",
+        "    name = 'java_runtime_toolchain',",
+        "    toolchain = ':jvm',",
+        "    toolchain_type = '"
+            + TestConstants.TOOLS_REPOSITORY
+            + "//tools/jdk:runtime_toolchain_type',",
+        ")");
+    scratch.file(
+        "a/rule.bzl",
+        "load('//myinfo:myinfo.bzl', 'MyInfo')",
+        "def _impl(ctx):",
+        "  provider = ctx.attr._java_runtime[java_common.JavaRuntimeInfo]",
+        "  return MyInfo(",
+        "    lib_ct_sym = provider.lib_ct_sym,",
+        "  )",
+        "jrule = rule(_impl, attrs = { '_java_runtime': attr.label(default=Label('//a:alias'))})");
+
+    useConfiguration("--extra_toolchains=//a:all");
+    ConfiguredTarget ct = getConfiguredTarget("//a:r");
+    StructImpl myInfo = getMyInfoFromTarget(ct);
+    @SuppressWarnings("unchecked")
+    Artifact libCtSym = (Artifact) myInfo.getValue("lib_ct_sym");
+    assertThat(libCtSym).isNotNull();
+    assertThat(libCtSym.getExecPathString()).isEqualTo("a/lib/ct.sym");
+  }
+
+  @Test
   @TestParameters({
     "{module: java_config, api: use_ijars}",
     "{module: java_config, api: disallow_java_import_exports}",
diff --git a/src/test/shell/bazel/BUILD b/src/test/shell/bazel/BUILD
index 33a2c26..30e1197 100644
--- a/src/test/shell/bazel/BUILD
+++ b/src/test/shell/bazel/BUILD
@@ -1,4 +1,6 @@
+load("@bazel_skylib//rules:write_file.bzl", "write_file")
 load("//:workspace_deps.bzl", "gen_workspace_stanza")
+load("//src/tools/bzlmod:utils.bzl", "get_canonical_repo_name")
 
 package(default_visibility = ["//visibility:private"])
 
@@ -216,15 +218,22 @@
     }),
 )
 
+write_file(
+    name = "gen_rules_java_repo_name",
+    out = "RULES_JAVA_REPO_NAME",
+    content = [get_canonical_repo_name("@rules_java")],
+)
+
 sh_test(
     name = "bazel_java17_test",
     srcs = ["bazel_java17_test.sh"],
     args = [
         # java_tools zip to test
-        "src/java_tools.zip",
-        "src/java_tools_prebuilt.zip",
+        "$(rlocationpath //src:java_tools_zip)",
+        "$(rlocationpath //src:java_tools_prebuilt_zip)",
     ],
     data = [
+        ":gen_rules_java_repo_name",
         ":test-deps",
         "//src:java_tools_prebuilt_zip",
         "//src:java_tools_zip",
@@ -244,6 +253,7 @@
         "released",
     ],
     data = [
+        ":gen_rules_java_repo_name",
         ":test-deps",
         "@bazel_tools//tools/bash/runfiles",
     ],
@@ -262,14 +272,15 @@
         srcs = ["bazel_java_test.sh"],
         args = [
             # java_tools zips to test
-            "src/java_tools.zip",
-            "src/java_tools_prebuilt.zip",
+            "$(rlocationpath //src:java_tools_zip)",
+            "$(rlocationpath //src:java_tools_prebuilt_zip)",
             # --java_language_version value
             java_version,
             # --java_runtime_version value
             java_version,
         ],
         data = [
+            ":gen_rules_java_repo_name",
             ":test-deps",
             "//src:java_tools_prebuilt_zip",
             "//src:java_tools_zip",
@@ -288,14 +299,15 @@
         srcs = ["bazel_java_test.sh"],
         args = [
             # java_tools zips to test
-            "$(LOCAL_JAVA_TOOLS_ZIP_URL)",
-            "$(LOCAL_JAVA_TOOLS_PREBUILT_ZIP_URL)",
+            "$(LOCAL_JAVA_TOOLS_ZIP_PATH)",
+            "$(LOCAL_JAVA_TOOLS_PREBUILT_ZIP_PATH)",
             # --java_language_version value
             java_version,
             # --java_runtime_version value
             java_version,
         ],
         data = [
+            ":gen_rules_java_repo_name",
             ":test-deps",
             "@bazel_tools//tools/bash/runfiles",
         ],
@@ -481,6 +493,7 @@
         "released",
     ],
     data = [
+        ":gen_rules_java_repo_name",
         ":test-deps",
     ],
     tags = [
@@ -504,6 +517,7 @@
             java_version,
         ],
         data = [
+            ":gen_rules_java_repo_name",
             ":test-deps",
         ],
         tags = [
@@ -521,17 +535,19 @@
         srcs = ["bazel_coverage_java_test.sh"],
         args = [
             # java_tools zips to test
-            "src/java_tools.zip",
-            "src/java_tools_prebuilt.zip",
-            # coverage output generator to test
-            "tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator/coverage",
+            "$(rlocationpath //src:java_tools_zip)",
+            "$(rlocationpath //src:java_tools_prebuilt_zip)",
+            # WORKSPACE file of the coverage output generator repo to test
+            "$(rlocationpath //tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator:coverage_empty_workspace)",
             # --java_runtime_version value
             java_version,
         ],
         data = [
+            ":gen_rules_java_repo_name",
             ":test-deps",
             "//src:java_tools_prebuilt_zip",
             "//src:java_tools_zip",
+            "//tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator:coverage_empty_workspace",
             "//tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator:coverage_output_generator_repo",
         ],
         tags = ["no_windows"],
diff --git a/src/test/shell/bazel/bazel_coverage_java_test.sh b/src/test/shell/bazel/bazel_coverage_java_test.sh
index 0c58508..de755c4 100755
--- a/src/test/shell/bazel/bazel_coverage_java_test.sh
+++ b/src/test/shell/bazel/bazel_coverage_java_test.sh
@@ -24,36 +24,34 @@
   || { echo "coverage_helpers.sh not found!" >&2; exit 1; }
 
 
+RULES_JAVA_REPO_NAME=$(cat "$(rlocation io_bazel/src/test/shell/bazel/RULES_JAVA_REPO_NAME)")
+JAVA_TOOLS_REPO_PREFIX="${RULES_JAVA_REPO_NAME}~toolchains~"
+
 JAVA_TOOLS_ZIP="$1"; shift
 if [[ "${JAVA_TOOLS_ZIP}" != "released" ]]; then
-    if [[ "${JAVA_TOOLS_ZIP}" == file* ]]; then
-        JAVA_TOOLS_ZIP_FILE_URL="${JAVA_TOOLS_ZIP}"
-    else
-        JAVA_TOOLS_ZIP_FILE_URL="file://$(rlocation io_bazel/$JAVA_TOOLS_ZIP)"
-    fi
+  JAVA_TOOLS_ZIP_FILE="$(rlocation "${JAVA_TOOLS_ZIP}")"
+  JAVA_TOOLS_DIR="$TEST_TMPDIR/_java_tools"
+  unzip -q "${JAVA_TOOLS_ZIP_FILE}" -d "$JAVA_TOOLS_DIR"
+  touch "$JAVA_TOOLS_DIR/WORKSPACE"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools=${JAVA_TOOLS_DIR}"
 fi
-JAVA_TOOLS_ZIP_FILE_URL=${JAVA_TOOLS_ZIP_FILE_URL:-}
 
 JAVA_TOOLS_PREBUILT_ZIP="$1"; shift
 if [[ "${JAVA_TOOLS_PREBUILT_ZIP}" != "released" ]]; then
-    if [[ "${JAVA_TOOLS_PREBUILT_ZIP}" == file* ]]; then
-        JAVA_TOOLS_PREBUILT_ZIP_FILE_URL="${JAVA_TOOLS_PREBUILT_ZIP}"
-    else
-        JAVA_TOOLS_PREBUILT_ZIP_FILE_URL="file://$(rlocation io_bazel/$JAVA_TOOLS_PREBUILT_ZIP)"
-    fi
-    # Remove the repo overrides that are set up some for Bazel CI workers.
-    inplace-sed "/override_repository=remote_java_tools=/d" "$TEST_TMPDIR/bazelrc"
-    inplace-sed "/override_repository=remote_java_tools_linux=/d" "$TEST_TMPDIR/bazelrc"
-    inplace-sed "/override_repository=remote_java_tools_windows=/d" "$TEST_TMPDIR/bazelrc"
-    inplace-sed "/override_repository=remote_java_tools_darwin_x86_64=/d" "$TEST_TMPDIR/bazelrc"
-    inplace-sed "/override_repository=remote_java_tools_darwin_arm64=/d" "$TEST_TMPDIR/bazelrc"
+  JAVA_TOOLS_PREBUILT_ZIP_FILE="$(rlocation "${JAVA_TOOLS_PREBUILT_ZIP}")"
+  JAVA_TOOLS_PREBUILT_DIR="$TEST_TMPDIR/_java_tools_prebuilt"
+  unzip -q "${JAVA_TOOLS_PREBUILT_ZIP_FILE}" -d "$JAVA_TOOLS_PREBUILT_DIR"
+  touch "$JAVA_TOOLS_PREBUILT_DIR/WORKSPACE"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools_linux=${JAVA_TOOLS_PREBUILT_DIR}"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools_windows=${JAVA_TOOLS_PREBUILT_DIR}"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools_darwin_x86_64=${JAVA_TOOLS_PREBUILT_DIR}"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools_arm64=${JAVA_TOOLS_PREBUILT_DIR}"
 fi
-JAVA_TOOLS_PREBUILT_ZIP_FILE_URL=${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL:-}
 
-COVERAGE_GENERATOR_DIR="$1"; shift
-if [[ "${COVERAGE_GENERATOR_DIR}" != "released" ]]; then
-  COVERAGE_GENERATOR_DIR="$(rlocation io_bazel/$COVERAGE_GENERATOR_DIR)"
-  add_to_bazelrc "build --override_repository=remote_coverage_tools=${COVERAGE_GENERATOR_DIR}"
+COVERAGE_GENERATOR_WORKSPACE_FILE="$1"; shift
+if [[ "${COVERAGE_GENERATOR_WORKSPACE_FILE}" != "released" ]]; then
+  COVERAGE_GENERATOR_DIR="$(dirname "$(rlocation $COVERAGE_GENERATOR_WORKSPACE_FILE)")"
+  add_to_bazelrc "build --override_repository=bazel_tools~remote_coverage_tools_extension~remote_coverage_tools=${COVERAGE_GENERATOR_DIR}"
 fi
 
 if [[ $# -gt 0 ]]; then
@@ -62,38 +60,6 @@
     add_to_bazelrc "build --tool_java_runtime_version=${JAVA_RUNTIME_VERSION}"
 fi
 
-function set_up() {
-    cat >>WORKSPACE <<EOF
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-# java_tools versions only used to test Bazel with various JDK toolchains.
-EOF
-
-    if [[ ! -z "${JAVA_TOOLS_ZIP_FILE_URL}" ]]; then
-    cat >>WORKSPACE <<EOF
-http_archive(
-    name = "remote_java_tools",
-    urls = ["${JAVA_TOOLS_ZIP_FILE_URL}"]
-)
-http_archive(
-    name = "remote_java_tools_linux",
-    urls = ["${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL}"]
-)
-http_archive(
-    name = "remote_java_tools_windows",
-    urls = ["${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL}"]
-)
-http_archive(
-    name = "remote_java_tools_darwin_x86_64",
-    urls = ["${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL}"]
-)
-http_archive(
-    name = "remote_java_tools_darwin_arm64",
-    urls = ["${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL}"]
-)
-EOF
-    fi
-}
-
 function test_java_test_coverage() {
   cat <<EOF > BUILD
 load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain")
diff --git a/src/test/shell/bazel/bazel_java17_test.sh b/src/test/shell/bazel/bazel_java17_test.sh
index a977927..7905022 100755
--- a/src/test/shell/bazel/bazel_java17_test.sh
+++ b/src/test/shell/bazel/bazel_java17_test.sh
@@ -54,53 +54,29 @@
   export MSYS2_ARG_CONV_EXCL="*"
 fi
 
+RULES_JAVA_REPO_NAME=$(cat "$(rlocation io_bazel/src/test/shell/bazel/RULES_JAVA_REPO_NAME)")
+JAVA_TOOLS_REPO_PREFIX="${RULES_JAVA_REPO_NAME}~toolchains~"
+
 JAVA_TOOLS_ZIP="$1"; shift
-JAVA_TOOLS_PREBUILT_ZIP="$1"; shift
-
-echo "JAVA_TOOLS_ZIP=$JAVA_TOOLS_ZIP"
-
-
-JAVA_TOOLS_RLOCATION=$(rlocation io_bazel/$JAVA_TOOLS_ZIP)
-
-if "$is_windows"; then
-    JAVA_TOOLS_ZIP_FILE_URL="file:///${JAVA_TOOLS_RLOCATION}"
-    JAVA_TOOLS_PREBUILT_ZIP_FILE_URL="file:///$(rlocation io_bazel/$JAVA_TOOLS_PREBUILT_ZIP)"
-else
-    JAVA_TOOLS_ZIP_FILE_URL="file://${JAVA_TOOLS_RLOCATION}"
-    JAVA_TOOLS_PREBUILT_ZIP_FILE_URL="file://$(rlocation io_bazel/$JAVA_TOOLS_PREBUILT_ZIP)"
+if [[ "${JAVA_TOOLS_ZIP}" != "released" ]]; then
+  JAVA_TOOLS_ZIP_FILE="$(rlocation "${JAVA_TOOLS_ZIP}")"
+  JAVA_TOOLS_DIR="$TEST_TMPDIR/_java_tools"
+  unzip -q "${JAVA_TOOLS_ZIP_FILE}" -d "$JAVA_TOOLS_DIR"
+  touch "$JAVA_TOOLS_DIR/WORKSPACE"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools=${JAVA_TOOLS_DIR}"
 fi
-JAVA_TOOLS_ZIP_FILE_URL=${JAVA_TOOLS_ZIP_FILE_URL:-}
-JAVA_TOOLS_PREBUILT_ZIP_FILE_URL=${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL:-}
 
-disable_bzlmod
-
-function set_up() {
-    cat >>WORKSPACE <<EOF
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-# java_tools versions only used to test Bazel with various JDK toolchains.
-
-http_archive(
-    name = "remote_java_tools",
-    urls = ["${JAVA_TOOLS_ZIP_FILE_URL}"]
-)
-http_archive(
-    name = "remote_java_tools_linux",
-    urls = ["${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL}"]
-)
-http_archive(
-    name = "remote_java_tools_windows",
-    urls = ["${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL}"]
-)
-http_archive(
-    name = "remote_java_tools_darwin_x86_64",
-    urls = ["${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL}"]
-)
-http_archive(
-    name = "remote_java_tools_darwin_arm64",
-    urls = ["${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL}"]
-)
-EOF
-}
+JAVA_TOOLS_PREBUILT_ZIP="$1"; shift
+if [[ "${JAVA_TOOLS_PREBUILT_ZIP}" != "released" ]]; then
+  JAVA_TOOLS_PREBUILT_ZIP_FILE="$(rlocation "${JAVA_TOOLS_PREBUILT_ZIP}")"
+  JAVA_TOOLS_PREBUILT_DIR="$TEST_TMPDIR/_java_tools_prebuilt"
+  unzip -q "${JAVA_TOOLS_PREBUILT_ZIP_FILE}" -d "$JAVA_TOOLS_PREBUILT_DIR"
+  touch "$JAVA_TOOLS_PREBUILT_DIR/WORKSPACE"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools_linux=${JAVA_TOOLS_PREBUILT_DIR}"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools_windows=${JAVA_TOOLS_PREBUILT_DIR}"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools_darwin_x86_64=${JAVA_TOOLS_PREBUILT_DIR}"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools_arm64=${JAVA_TOOLS_PREBUILT_DIR}"
+fi
 
 # Java source files version shall match --java_language_version_flag version.
 function test_java17_text_block() {
diff --git a/src/test/shell/bazel/bazel_java_test.sh b/src/test/shell/bazel/bazel_java_test.sh
index 88786c3..1dda5b4 100755
--- a/src/test/shell/bazel/bazel_java_test.sh
+++ b/src/test/shell/bazel/bazel_java_test.sh
@@ -59,35 +59,29 @@
 
 JAVA_TOOLCHAIN_TYPE="@bazel_tools//tools/jdk:toolchain_type"
 
+RULES_JAVA_REPO_NAME=$(cat "$(rlocation io_bazel/src/test/shell/bazel/RULES_JAVA_REPO_NAME)")
+JAVA_TOOLS_REPO_PREFIX="${RULES_JAVA_REPO_NAME}~toolchains~"
+
 JAVA_TOOLS_ZIP="$1"; shift
 if [[ "${JAVA_TOOLS_ZIP}" != "released" ]]; then
-  if [[ "${JAVA_TOOLS_ZIP}" == file* ]]; then
-    JAVA_TOOLS_ZIP_FILE_URL="${JAVA_TOOLS_ZIP}"
-  elif "$is_windows"; then
-    JAVA_TOOLS_ZIP_FILE_URL="file:///$(rlocation io_bazel/$JAVA_TOOLS_ZIP)"
-  else
-    JAVA_TOOLS_ZIP_FILE_URL="file://$(rlocation io_bazel/$JAVA_TOOLS_ZIP)"
-  fi
+  JAVA_TOOLS_ZIP_FILE="$(rlocation "${JAVA_TOOLS_ZIP}")"
+  JAVA_TOOLS_DIR="$TEST_TMPDIR/_java_tools"
+  unzip -q "${JAVA_TOOLS_ZIP_FILE}" -d "$JAVA_TOOLS_DIR"
+  touch "$JAVA_TOOLS_DIR/WORKSPACE"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools=${JAVA_TOOLS_DIR}"
 fi
-JAVA_TOOLS_ZIP_FILE_URL=${JAVA_TOOLS_ZIP_FILE_URL:-}
 
 JAVA_TOOLS_PREBUILT_ZIP="$1"; shift
 if [[ "${JAVA_TOOLS_PREBUILT_ZIP}" != "released" ]]; then
-  if [[ "${JAVA_TOOLS_PREBUILT_ZIP}" == file* ]]; then
-    JAVA_TOOLS_PREBUILT_ZIP_FILE_URL="${JAVA_TOOLS_PREBUILT_ZIP}"
-  elif "$is_windows"; then
-    JAVA_TOOLS_PREBUILT_ZIP_FILE_URL="file:///$(rlocation io_bazel/$JAVA_TOOLS_PREBUILT_ZIP)"
-  else
-    JAVA_TOOLS_PREBUILT_ZIP_FILE_URL="file://$(rlocation io_bazel/$JAVA_TOOLS_PREBUILT_ZIP)"
-  fi
-  # Remove the repo overrides that are set up for some Bazel CI workers.
-  inplace-sed "/override_repository=remote_java_tools=/d" "$TEST_TMPDIR/bazelrc"
-  inplace-sed "/override_repository=remote_java_tools_linux=/d" "$TEST_TMPDIR/bazelrc"
-  inplace-sed "/override_repository=remote_java_tools_windows=/d" "$TEST_TMPDIR/bazelrc"
-  inplace-sed "/override_repository=remote_java_tools_darwin_x86_64=/d" "$TEST_TMPDIR/bazelrc"
-  inplace-sed "/override_repository=remote_java_tools_darwin_arm64=/d" "$TEST_TMPDIR/bazelrc"
+  JAVA_TOOLS_PREBUILT_ZIP_FILE="$(rlocation "${JAVA_TOOLS_PREBUILT_ZIP}")"
+  JAVA_TOOLS_PREBUILT_DIR="$TEST_TMPDIR/_java_tools_prebuilt"
+  unzip -q "${JAVA_TOOLS_PREBUILT_ZIP_FILE}" -d "$JAVA_TOOLS_PREBUILT_DIR"
+  touch "$JAVA_TOOLS_PREBUILT_DIR/WORKSPACE"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools_linux=${JAVA_TOOLS_PREBUILT_DIR}"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools_windows=${JAVA_TOOLS_PREBUILT_DIR}"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools_darwin_x86_64=${JAVA_TOOLS_PREBUILT_DIR}"
+  add_to_bazelrc "build --override_repository=${JAVA_TOOLS_REPO_PREFIX}remote_java_tools_arm64=${JAVA_TOOLS_PREBUILT_DIR}"
 fi
-JAVA_TOOLS_PREBUILT_ZIP_FILE_URL=${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL:-}
 
 if [[ $# -gt 0 ]]; then
   JAVA_LANGUAGE_VERSION="$1"; shift
@@ -111,38 +105,6 @@
 
 export TESTENV_DONT_BAZEL_CLEAN=1
 
-function set_up() {
-  cat >>WORKSPACE <<EOF
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-# java_tools versions only used to test Bazel with various JDK toolchains.
-EOF
-
-  if [[ ! -z "${JAVA_TOOLS_ZIP_FILE_URL}" ]]; then
-    cat >>WORKSPACE <<EOF
-http_archive(
-    name = "remote_java_tools",
-    urls = ["${JAVA_TOOLS_ZIP_FILE_URL}"]
-)
-http_archive(
-    name = "remote_java_tools_linux",
-    urls = ["${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL}"]
-)
-http_archive(
-    name = "remote_java_tools_windows",
-    urls = ["${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL}"]
-)
-http_archive(
-    name = "remote_java_tools_darwin_x86_64",
-    urls = ["${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL}"]
-)
-http_archive(
-    name = "remote_java_tools_darwin_arm64",
-    urls = ["${JAVA_TOOLS_PREBUILT_ZIP_FILE_URL}"]
-)
-EOF
-  fi
-}
-
 function tear_down() {
   rm -rf "$(bazel info bazel-bin)/java"
 }
@@ -1965,5 +1927,25 @@
   expect_log "in pkg/Library.java: ''"
 }
 
+function test_header_compiler_direct_supports_release() {
+  if [[ "${JAVA_TOOLS_PREBUILT_ZIP}" == "released" ]]; then
+    # TODO: Remove after the next java_tools release.
+    return
+  fi
+
+  mkdir -p pkg
+  cat << 'EOF' > pkg/BUILD
+java_library(name = "a", srcs = ["A.java"], deps = [":b"])
+java_library(name = "b", srcs = ["B.java"], javacopts = ["--release", "11"])
+EOF
+  cat << 'EOF' > pkg/A.java
+public class A extends B {}
+EOF
+  cat << 'EOF' > pkg/B.java
+public class B {}
+EOF
+
+  bazel build //pkg:a >& $TEST_log || fail "build failed"
+}
 
 run_suite "Java integration tests"
diff --git a/src/upload_all_java_tools.sh b/src/upload_all_java_tools.sh
index d3e94c7..7e4fe7b 100755
--- a/src/upload_all_java_tools.sh
+++ b/src/upload_all_java_tools.sh
@@ -63,13 +63,8 @@
 prebuilt_zip_path=${PWD}/bazel-bin/src/java_tools_prebuilt.zip
 
 if [[ "$platform" == "windows" ]]; then
-    # Windows needs "file:///c:/foo/bar".
-    file_url="file:///$(cygpath -m ${zip_path})"
-    prebuilt_file_url="file:///$(cygpath -m ${prebuilt_zip_path})"
-else
-    # Non-Windows needs "file:///foo/bar".
-    file_url="file://${zip_path}"
-    prebuilt_file_url="file://${prebuilt_zip_path}"
+    zip_path="$(cygpath -m "${zip_path}")"
+    prebuilt_zip_path="$(cygpath -m "${prebuilt_zip_path}")"
 fi
 
 # Skip for now, as the test is broken on Windows.
@@ -79,8 +74,8 @@
     for java_version in $JAVA_VERSIONS; do
         bazel test --verbose_failures --test_output=all --nocache_test_results \
             //src/test/shell/bazel:bazel_java_test_local_java_tools_jdk${java_version} \
-            --define=LOCAL_JAVA_TOOLS_ZIP_URL="${file_url}" \
-            --define=LOCAL_JAVA_TOOLS_PREBUILT_ZIP_URL="${prebuilt_file_url}"
+            --define=LOCAL_JAVA_TOOLS_ZIP_PATH="${zip_path}" \
+            --define=LOCAL_JAVA_TOOLS_PREBUILT_ZIP_PATH="${prebuilt_zip_path}"
     done
 fi
 
diff --git a/tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator/BUILD b/tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator/BUILD
index 4593cb9..4eeab00 100644
--- a/tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator/BUILD
+++ b/tools/test/CoverageOutputGenerator/java/com/google/devtools/coverageoutputgenerator/BUILD
@@ -211,6 +211,7 @@
     name = "coverage_empty_workspace",
     outs = ["coverage/WORKSPACE"],
     cmd = "touch $@",
+    visibility = ["//src/test/shell/bazel:__pkg__"],
 )
 
 # Used to act as an override for @remote_coverage_tools in integration tests