Repository: bazelbuild/bazel
Issue: sh_test: @bazel_tools//tools/jdk:current_host_java_runtime is not provided in runfiles directory
Labels: P2
team-Rules-Java

While `"@bazel_tools//tools/jdk:current_java_runtime"` is provided in runfiles dierctory (as expected), `"@bazel_tools//tools/jdk:current_host_java_runtime"` is not.

Working reproducer:

WORKSPACE:
```python
workspace(name = "foo")
```

BUILD:
```python
sh_test(
    name = "bar",
    args = ["$(JAVABASE)/bin/java"],
    data = ["@bazel_tools//tools/jdk:current_java_runtime"],
    srcs = ["run.sh"],
    tags = [
        "local",
        "manual"
    ],
    toolchains = ["@bazel_tools//tools/jdk:current_java_runtime"],
)
```

run.sh:
```bash
#!/bin/bash

set -eu

JAVA=$1
[[ "$JAVA" =~ ^(/|[^/]+$) ]] || JAVA="$PWD/$JAVA"

"${JAVA}" -fullversion
```

And executing the test works as expected:

```
  $ bazel test bar
  INFO: Analyzed target //:bar (1 packages loaded, 369 targets configured).
INFO: Found 1 test target...
Target //:bar up-to-date:
  bazel-bin/bar
INFO: Elapsed time: 0.419s, Critical Path: 0.15s
INFO: 2 processes: 2 local.
INFO: Build completed successfully, 4 total actions
//:bar                                                                   PASSED in 0.1s

Executed 1 out of 1 test: 1 test passes.
INFO: Build completed successfully, 4 total actions
```

And the content of tests.log is:

```
Executing tests from //:bar
-----------------------------------------------------------------------------
java full version "1.8.0_171-b11"
```

Now apply this diff to the working version above:

```diff
$ git diff
diff --git a/BUILD b/BUILD
index e820161..aa678ae 100644
--- a/BUILD
+++ b/BUILD
@@ -1,11 +1,11 @@
 sh_test(
     name = "bar",
     args = ["$(JAVABASE)/bin/java"],
-    data = ["@bazel_tools//tools/jdk:current_java_runtime"],
+    data = ["@bazel_tools//tools/jdk:current_host_java_runtime"],
     srcs = ["run.sh"],
     tags = [
         "local",
         "manual"
     ],
-    toolchains = ["@bazel_tools//tools/jdk:current_java_runtime"],
+    toolchains = ["@bazel_tools//tools/jdk:current_host_java_runtime"],
 )
```

Now the test is failing:

```
[...]
bazel-out/k8-fastbuild/bin/bar.runfiles/foo/external/remotejdk11_linux/bin/java: No such file or directory
```

Background: Gerrit Code Review supports also building with alternative build toolchains, see: [1]:

```
  $ bazel build \
  --host_javabase=@bazel_tools//tools/jdk:remote_jdk11 \
  --javabase=@bazel_tools//tools/jdk:remote_jdk11 \
  --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_java11 \
  --java_toolchain=@bazel_tools//tools/jdk:toolchain_java11 \
  :release
```

We also have some tests in place, that are trying to run final artifact `gerrit.war`. But in the use case above, it was built with remote JDK 11 and thus produced the byte code with major version 55, even though the local JDK is still 8, and that why the tests are failing: [2]

```
#### TEST_SRCDIR = /home/jenkins/.cache/bazel/_bazel_jenkins/3c163556d578d35cc78b8cfe3938f51f/execroot/gerrit/bazel-out/k8-fastbuild/bin/prologtests/examples/test_examples.runfiles
/home/jenkins/.cache/bazel/_bazel_jenkins/3c163556d578d35cc78b8cfe3938f51f/execroot/gerrit/bazel-out/k8-fastbuild/bin/prologtests/examples/test_examples.runfiles/gerrit/prologtests/examples /home/jenkins/.cache/bazel/_bazel_jenkins/3c163556d578d35cc78b8cfe3938f51f/execroot/gerrit/bazel-out/k8-fastbuild/bin/prologtests/examples/test_examples.runfiles/gerrit
### Running test t1.pl
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: Main has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
```

So, the solution is not just to call `java -jar gerrit.war` in the test, but pass the current  `@bazel_tools//tools/jdk:current_host_java_runtime` into the test and use the right JDK runtime.

Unfortunately this doesn't seem to work, see the attempt to fix it here: [3].

[1] https://gerrit-review.googlesource.com/c/gerrit/+/235795
[2] http://paste.openstack.org/show/n0YoCw2AI1pLQcfycAad/
[3] https://gerrit-review.googlesource.com/c/gerrit/+/237472

Issue comments:
@davido Thank you for the detailed bug report, it's great! :) Indeed I checked and the implementation for [java_host_runtime_alias](https://github.com/bazelbuild/bazel/blob/master/tools/jdk/java_toolchain_alias.bzl#L46) doesn't add its files to runfiles. @cushon is there a reason why `java_host_runtime_alias` doesn't return `runfiles` (as opposed to `java_runtime_alias`) or was it implemented this way simply because there was no use case for using the host javabase?
> But in the use case above, it was built with remote JDK 11 and thus produced the byte code with major version 55, even though the local JDK is still 8, and that why the tests are failing.

Can you provide more context about the original problem you were trying to solve? What does the local JDK 8 have to do with the test failure, if you're setting both `--host_javabase` and `--javabase` to JDK 11?

> java_host_runtime_alias doesn't return runfiles

It propagates `DefaultInfo`, is that not sufficient?
> Can you provide more context about the original problem you were trying to solve?

We are running not Java tests, but prolog tests. The way it's working is: we run `java -jar gerrit.war ` and invoke `prolog-shell` site-program and passing interactively prolog input file, the code is here: [1]:

```
  $ java -jar ${GERRIT_WAR} prolog-shell -q -s load.pl
```

The invocation is here: [2]:

```
sh_test(
    name = "test_examples",
    srcs = ["run.sh"],
    data = glob(["*.pl"]) + ["//:gerrit.war"],
)
```

I'm trying to fix it here, but it doesn't work, unfortunately: [3].

> It propagates DefaultInfo, is that not sufficient?

How can I use it to access `remote_jdk11linux/bin/java` from within `run.sh` bash script?

[1] https://github.com/GerritCodeReview/gerrit/blob/master/prologtests/examples/run.sh#L39
[2] https://github.com/GerritCodeReview/gerrit/blob/master/prologtests/examples/BUILD#L3
[3] https://gerrit-review.googlesource.com/c/gerrit/+/237472
> It propagates DefaultInfo, is that not sufficient?

I sent a fix in #9398 to create a new provider rather than returning the propagated one. Initially I didn't see the returned `runtime[DefaultInfo]`, but apparently it wasn't enough (or correct?). I asked about this in the PR.

Pull request review comments:

Patch that resolved the issue:
diff --git a/tools/jdk/java_toolchain_alias.bzl b/tools/jdk/java_toolchain_alias.bzl
index 81b78120673933..f9c2a7123cc881 100644
--- a/tools/jdk/java_toolchain_alias.bzl
+++ b/tools/jdk/java_toolchain_alias.bzl
@@ -46,10 +46,14 @@ java_runtime_alias = rule(
 def _java_host_runtime_alias(ctx):
     """An experimental implementation of java_host_runtime_alias using toolchain resolution."""
     runtime = ctx.attr._runtime
+    toolchain = runtime[java_common.JavaRuntimeInfo]
     return [
-        runtime[java_common.JavaRuntimeInfo],
+        toolchain,
         runtime[platform_common.TemplateVariableInfo],
-        runtime[DefaultInfo],
+        DefaultInfo(
+            runfiles = ctx.runfiles(transitive_files = toolchain.files),
+            files = toolchain.files,
+        ),
     ]
 
 java_host_runtime_alias = rule(


Test patch: