Fix #7304: Validate that JAVA_HOME points to a JDK.

If JAVA_HOME is not valid, fallback to the detection by looking up the
`javac` binary.

This also fixes an issue where Bazel would try to look up the boot classpath
for JDK 8 in the wrong folder: By convention, OpenJDK 8 has a directory
structure, where the JRE is in a subdirectory of the JDK:

/usr/lib/jvm/java-8-openjdk-amd64 <- JDK
/usr/lib/jvm/java-8-openjdk-amd64/jre <- JRE

This changed with OpenJDK 9 and newer and there is no longer a `jre`
folder for these versions (and newer Java versions are not supplied as a
separate "JRE" version anymore, there is only a "JDK").

On some platforms (e.g. Debian) the JAVA_HOME of an installed OpenJDK 8
might point to the JRE instead of the JDK, which triggers a bug in the
boot classpath detection logic in Bazel's DumpPlatformClassPath tool:
The tool relies on the directory structure as mentioned above to
determine whether it is looking at a OpenJDK 8 or OpenJDK >= 9. If
certain well-known files (e.g. "jre/lib/rt.jar") of OpenJDK 8 don't
exist, it assumes that it's looking at an OpenJDK 9+ - unfortunately
this is also the case when you're looking at something that's not a JDK
at all or the `jre` subfolder of an OpenJDK 8.

This triggers an InvalidArgumentException in the Javac code.

By making sure that we only ever pass a valid JDK path to that tool, the
problem can no longer happen.

RELNOTES: Bazel now validates that JAVA_HOME points to a valid JDK and
falls back to auto-detection by looking up the path of `javac`.

Closes #7324.

PiperOrigin-RevId: 232197212
diff --git a/src/main/cpp/blaze_util_darwin.cc b/src/main/cpp/blaze_util_darwin.cc
index 456e851..d20169c 100644
--- a/src/main/cpp/blaze_util_darwin.cc
+++ b/src/main/cpp/blaze_util_darwin.cc
@@ -36,6 +36,7 @@
 #include "src/main/cpp/util/exit_code.h"
 #include "src/main/cpp/util/file.h"
 #include "src/main/cpp/util/logging.h"
+#include "src/main/cpp/util/path.h"
 #include "src/main/cpp/util/strings.h"
 
 namespace blaze {
@@ -162,7 +163,12 @@
 string GetSystemJavabase() {
   string java_home = GetEnv("JAVA_HOME");
   if (!java_home.empty()) {
-    return java_home;
+    string javac = blaze_util::JoinPath(java_home, "bin/javac");
+    if (access(javac.c_str(), X_OK) == 0) {
+      return java_home;
+    }
+    BAZEL_LOG(WARNING)
+        << "Ignoring JAVA_HOME, because it must point to a JDK, not a JRE.";
   }
 
   // java_home will print a warning if no JDK could be found
diff --git a/src/main/cpp/blaze_util_freebsd.cc b/src/main/cpp/blaze_util_freebsd.cc
index ed7ec49..b972168 100644
--- a/src/main/cpp/blaze_util_freebsd.cc
+++ b/src/main/cpp/blaze_util_freebsd.cc
@@ -141,7 +141,17 @@
 string GetSystemJavabase() {
   // if JAVA_HOME is defined, then use it as default.
   string javahome = GetEnv("JAVA_HOME");
-  return !javahome.empty() ? javahome : "/usr/local/openjdk8";
+
+  if (!javahome.empty()) {
+    string javac = blaze_util::JoinPath(javahome, "bin/javac");
+    if (access(javac.c_str(), X_OK) == 0) {
+      return javahome;
+    }
+    BAZEL_LOG(WARNING)
+        << "Ignoring JAVA_HOME, because it must point to a JDK, not a JRE.";
+  }
+
+  return "/usr/local/openjdk8";
 }
 
 void WriteSystemSpecificProcessIdentifier(
diff --git a/src/main/cpp/blaze_util_linux.cc b/src/main/cpp/blaze_util_linux.cc
index cf1b0de..3801028 100644
--- a/src/main/cpp/blaze_util_linux.cc
+++ b/src/main/cpp/blaze_util_linux.cc
@@ -165,7 +165,12 @@
   // if JAVA_HOME is defined, then use it as default.
   string javahome = GetEnv("JAVA_HOME");
   if (!javahome.empty()) {
-    return javahome;
+    string javac = blaze_util::JoinPath(javahome, "bin/javac");
+    if (access(javac.c_str(), X_OK) == 0) {
+      return javahome;
+    }
+    BAZEL_LOG(WARNING)
+        << "Ignoring JAVA_HOME, because it must point to a JDK, not a JRE.";
   }
 
   // which javac
diff --git a/src/main/cpp/blaze_util_windows.cc b/src/main/cpp/blaze_util_windows.cc
index 038ad50..3d01b44 100644
--- a/src/main/cpp/blaze_util_windows.cc
+++ b/src/main/cpp/blaze_util_windows.cc
@@ -459,10 +459,16 @@
 
 string GetSystemJavabase() {
   string javahome(GetEnv("JAVA_HOME"));
-  if (javahome.empty()) {
-    return "";
+  if (!javahome.empty()) {
+    string javac = blaze_util::JoinPath(javahome, "bin/javac.exe");
+    if (blaze_util::PathExists(javac.c_str())) {
+      return javahome;
+    }
+    BAZEL_LOG(WARNING)
+        << "Ignoring JAVA_HOME, because it must point to a JDK, not a JRE.";
   }
-  return javahome;
+
+  return "";
 }
 
 namespace {