Wire up `oneversion` tool in `java_tools`

* Add a prebuilt `one_version` tool as well as sources to `java_tools`.
* Avoid passing `--whitelist` to `one_version` if no allowlist is configured in the toolchain as it isn't supported by the Bazel version of `oneversion` yet.
* Document the `one_version` flags.
* Clean up tests not updated after recent rules_java releases.

Work towards #1071

Closes #22246.

PiperOrigin-RevId: 640177996
Change-Id: I0323154274bf2127a023184a67485783aa868461
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index f856fc8..fcd1fc0 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -30,6 +30,7 @@
       - "//src/main/starlark/tests/builtins_bzl/..."
       - "//src/test/..."
       - "//src/tools/execlog/..."
+      - "//src/tools/one_version/..."
       - "//src/tools/singlejar/..."
       - "//src/tools/workspacelog/..."
       - "//third_party/ijar/..."
@@ -90,6 +91,7 @@
       - "//src/main/starlark/tests/builtins_bzl/..."
       - "//src/test/..."
       - "//src/tools/execlog/..."
+      - "//src/tools/one_version/..."
       - "//src/tools/singlejar/..."
       - "//src/tools/workspacelog/..."
       - "//third_party/ijar/..."
@@ -149,6 +151,7 @@
       - "//src/main/starlark/tests/builtins_bzl/..."
       - "//src/test/..."
       - "//src/tools/execlog/..."
+      - "//src/tools/one_version/..."
       - "//src/tools/singlejar/..."
       - "//src/tools/workspacelog/..."
       - "//third_party/ijar/..."
@@ -183,6 +186,7 @@
       - "//src/main/starlark/tests/builtins_bzl/..."
       - "//src/test/..."
       - "//src/tools/execlog/..."
+      - "//src/tools/one_version/..."
       - "//src/tools/singlejar/..."
       - "//src/tools/workspacelog/..."
       - "//third_party/ijar/..."
@@ -282,6 +286,7 @@
       - "//src/main/starlark/tests/builtins_bzl/..."
       - "//src/test/..."
       - "//src/tools/execlog/..."
+      - "//src/tools/one_version/..."
       - "//src/tools/singlejar/..."
       - "//src/tools/workspacelog/..."
       - "//third_party/ijar/..."
@@ -329,6 +334,7 @@
       - "//src/test/res/..."
       - "//src/test/shell/..."
       - "//src/tools/launcher/..."
+      - "//src/tools/one_version/..."
       - "//src/tools/singlejar/..."
       - "//third_party/def_parser/..."
       - "//tools/android/..."
@@ -405,6 +411,7 @@
       - "//src/main/starlark/tests/builtins_bzl/..."
       - "//src/test/..."
       - "//src/tools/execlog/..."
+      - "//src/tools/one_version/..."
       - "//src/tools/singlejar/..."
       - "//src/tools/workspacelog/..."
       - "//third_party/ijar/..."
diff --git a/.bazelrc b/.bazelrc
index ca4cb7f..2bf7a17 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -23,7 +23,7 @@
 # Alias
 build:remote --config=ubuntu2004
 
-build:macos --macos_minimum_os=10.11
+build:macos --macos_minimum_os=10.13
 
 # On Windows, we need pywin32 pip package, which doesn't work with the Python hermetic toolchain.
 # See https://github.com/bazelbuild/rules_python/issues/1356
diff --git a/MODULE.bazel b/MODULE.bazel
index 765b299..3af3c55 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -30,9 +30,9 @@
 bazel_dep(name = "rules_jvm_external", version = "6.0")
 bazel_dep(name = "rules_python", version = "0.28.0")
 bazel_dep(name = "rules_testing", version = "0.6.0")
-bazel_dep(name = "googletest", version = "1.14.0", repo_name = "com_google_googletest")
+bazel_dep(name = "googletest", version = "1.14.0.bcr.1", repo_name = "com_google_googletest")
 bazel_dep(name = "with_cfg.bzl", version = "0.2.4")
-bazel_dep(name = "abseil-cpp", version = "20230125.1")
+bazel_dep(name = "abseil-cpp", version = "20240116.2")
 
 # TODO(fmeum): Remove the dependency on buildozer after Bazel is built with 7.2.0.
 bazel_dep(name = "buildozer", version = "7.1.2")
diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock
index b314c8a..511b225 100644
--- a/MODULE.bazel.lock
+++ b/MODULE.bazel.lock
@@ -1,6 +1,6 @@
 {
   "lockFileVersion": 6,
-  "moduleFileHash": "818d3d6a05f9446d49a9ca71484dc5d06317e39de0bfcf6580cdf260243c0150",
+  "moduleFileHash": "510c7c32da0bf633c73a9f30ce2e4cff965074f1a2134ffe8bd17612d5f621b6",
   "flags": {
     "cmdRegistries": [
       "https://bcr.bazel.build/"
@@ -647,9 +647,9 @@
         "rules_jvm_external": "rules_jvm_external@6.0",
         "rules_python": "rules_python@0.28.0",
         "rules_testing": "rules_testing@0.6.0",
-        "com_google_googletest": "googletest@1.14.0",
+        "com_google_googletest": "googletest@1.14.0.bcr.1",
         "with_cfg.bzl": "with_cfg.bzl@0.2.4",
-        "abseil-cpp": "abseil-cpp@20230125.1",
+        "abseil-cpp": "abseil-cpp@20240116.2",
         "buildozer": "buildozer@7.1.2",
         "remoteapis": "remoteapis@_",
         "googleapis": "googleapis@_",
@@ -775,11 +775,11 @@
         "rules_proto": "rules_proto@5.3.0-21.7",
         "rules_java": "rules_java@7.6.1",
         "rules_pkg": "rules_pkg@0.9.1",
-        "com_google_abseil": "abseil-cpp@20230125.1",
+        "com_google_abseil": "abseil-cpp@20240116.2",
         "zlib": "zlib@1.3",
         "upb": "upb@0.0.0-20220923-a547704",
         "rules_jvm_external": "rules_jvm_external@6.0",
-        "com_google_googletest": "googletest@1.14.0",
+        "com_google_googletest": "googletest@1.14.0.bcr.1",
         "bazel_tools": "bazel_tools@_",
         "local_config_platform": "local_config_platform@_"
       },
@@ -852,9 +852,9 @@
         "bazel_skylib": "bazel_skylib@1.6.1",
         "boringssl": "boringssl@0.0.0-20211025-d4f1ab9",
         "com_github_cares_cares": "c-ares@1.15.0",
-        "com_google_absl": "abseil-cpp@20230125.1",
+        "com_google_absl": "abseil-cpp@20240116.2",
         "com_google_protobuf": "protobuf@21.7",
-        "com_googlesource_code_re2": "re2@2021-09-01",
+        "com_googlesource_code_re2": "re2@2023-09-01",
         "rules_proto": "rules_proto@5.3.0-21.7",
         "upb": "upb@0.0.0-20220923-a547704",
         "zlib": "zlib@1.3",
@@ -1808,18 +1808,19 @@
         }
       }
     },
-    "googletest@1.14.0": {
+    "googletest@1.14.0.bcr.1": {
       "name": "googletest",
-      "version": "1.14.0",
-      "key": "googletest@1.14.0",
+      "version": "1.14.0.bcr.1",
+      "key": "googletest@1.14.0.bcr.1",
       "repoName": "googletest",
       "executionPlatformsToRegister": [],
       "toolchainsToRegister": [],
       "extensionUsages": [],
       "deps": {
-        "com_google_absl": "abseil-cpp@20230125.1",
+        "com_google_absl": "abseil-cpp@20240116.2",
         "platforms": "platforms@0.0.9",
         "rules_cc": "rules_cc@0.0.9",
+        "com_googlesource_code_re2": "re2@2023-09-01",
         "bazel_tools": "bazel_tools@_",
         "local_config_platform": "local_config_platform@_"
       },
@@ -1833,7 +1834,7 @@
           "integrity": "sha256-itWYxzrXluDYKAsILOvYKmMNc+c808cAV5OKZQG7pdc=",
           "strip_prefix": "googletest-1.14.0",
           "remote_patches": {
-            "https://bcr.bazel.build/modules/googletest/1.14.0/patches/module_dot_bazel.patch": "sha256-CSomzvti38LCuURDG5EEoa3O1tQF3cKKt/mknnP1qcc="
+            "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/patches/module_dot_bazel.patch": "sha256-jijctisPYOzP4X4cl0K7neRh/kqJB+yODNHf8V8heCE="
           },
           "remote_patch_strip": 0
         }
@@ -1868,18 +1869,18 @@
         }
       }
     },
-    "abseil-cpp@20230125.1": {
+    "abseil-cpp@20240116.2": {
       "name": "abseil-cpp",
-      "version": "20230125.1",
-      "key": "abseil-cpp@20230125.1",
+      "version": "20240116.2",
+      "key": "abseil-cpp@20240116.2",
       "repoName": "abseil-cpp",
       "executionPlatformsToRegister": [],
       "toolchainsToRegister": [],
       "extensionUsages": [],
       "deps": {
-        "rules_cc": "rules_cc@0.0.9",
-        "platforms": "platforms@0.0.9",
         "bazel_skylib": "bazel_skylib@1.6.1",
+        "com_google_googletest": "googletest@1.14.0.bcr.1",
+        "platforms": "platforms@0.0.9",
         "bazel_tools": "bazel_tools@_",
         "local_config_platform": "local_config_platform@_"
       },
@@ -1888,13 +1889,11 @@
         "ruleClassName": "http_archive",
         "attributes": {
           "urls": [
-            "https://github.com/abseil/abseil-cpp/archive/refs/tags/20230125.1.tar.gz"
+            "https://github.com/abseil/abseil-cpp/releases/download/20240116.2/abseil-cpp-20240116.2.tar.gz"
           ],
-          "integrity": "sha256-gTEcF1mbNxIGne0gzKCaYqsL8qid+haZN4bIeCt+0UU=",
-          "strip_prefix": "abseil-cpp-20230125.1",
-          "remote_patches": {
-            "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/patches/module_dot_bazel.patch": "sha256-L1wChhBmDOnRbPbD4MENVXHjOBT2KFrDxT6D+aoThxk="
-          },
+          "integrity": "sha256-czcmuMOm05pBINfkXqi0GkNM2s3kAculAPFCNsSbOdw=",
+          "strip_prefix": "abseil-cpp-20240116.2",
+          "remote_patches": {},
           "remote_patch_strip": 0
         }
       }
@@ -2366,7 +2365,7 @@
         "bazel_skylib": "bazel_skylib@1.6.1",
         "rules_proto": "rules_proto@5.3.0-21.7",
         "com_google_protobuf": "protobuf@21.7",
-        "com_google_absl": "abseil-cpp@20230125.1",
+        "com_google_absl": "abseil-cpp@20240116.2",
         "platforms": "platforms@0.0.9",
         "bazel_tools": "bazel_tools@_",
         "local_config_platform": "local_config_platform@_"
@@ -2588,16 +2587,52 @@
         }
       }
     },
-    "re2@2021-09-01": {
+    "re2@2023-09-01": {
       "name": "re2",
-      "version": "2021-09-01",
-      "key": "re2@2021-09-01",
+      "version": "2023-09-01",
+      "key": "re2@2023-09-01",
       "repoName": "re2",
       "executionPlatformsToRegister": [],
       "toolchainsToRegister": [],
-      "extensionUsages": [],
+      "extensionUsages": [
+        {
+          "extensionBzlFile": "@pybind11_bazel//:python_configure.bzl",
+          "extensionName": "extension",
+          "usingModule": "re2@2023-09-01",
+          "location": {
+            "file": "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel",
+            "line": 22,
+            "column": 33
+          },
+          "imports": {
+            "local_config_python": "local_config_python",
+            "pybind11": "pybind11"
+          },
+          "devImports": [],
+          "tags": [
+            {
+              "tagName": "toolchain",
+              "attributeValues": {
+                "python_version": "3"
+              },
+              "devDependency": false,
+              "location": {
+                "file": "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel",
+                "line": 23,
+                "column": 27
+              }
+            }
+          ],
+          "hasDevUseExtension": false,
+          "hasNonDevUseExtension": true
+        }
+      ],
       "deps": {
+        "platforms": "platforms@0.0.9",
         "rules_cc": "rules_cc@0.0.9",
+        "com_google_absl": "abseil-cpp@20240116.2",
+        "rules_python": "rules_python@0.28.0",
+        "pybind11_bazel": "pybind11_bazel@2.11.1",
         "bazel_tools": "bazel_tools@_",
         "local_config_platform": "local_config_platform@_"
       },
@@ -2606,12 +2641,12 @@
         "ruleClassName": "http_archive",
         "attributes": {
           "urls": [
-            "https://github.com/google/re2/archive/refs/tags/2021-09-01.zip"
+            "https://github.com/google/re2/releases/download/2023-09-01/re2-2023-09-01.zip"
           ],
-          "integrity": "sha256-739ELobFx96SqV7QdeOUNre0fFKk5+5jV1IU7slG/C8=",
-          "strip_prefix": "re2-2021-09-01",
+          "integrity": "sha256-IkuDUdxGM7EBLb2EdWTgYKRr5goioUY9S1uZP9S/Wcw=",
+          "strip_prefix": "re2-2023-09-01",
           "remote_patches": {
-            "https://bcr.bazel.build/modules/re2/2021-09-01/patches/module_dot_bazel.patch": "sha256-uLpoNV5fETcQxOqvD9PtPv4CHYhetfPSkPIJPXoLXcg="
+            "https://bcr.bazel.build/modules/re2/2023-09-01/patches/module_dot_bazel.patch": "sha256-MUQkRNgPJ0lbYqOXoBu2m2vLH7IuKEbK/VWTw7WWrnA="
           },
           "remote_patch_strip": 0
         }
@@ -2786,6 +2821,34 @@
           "remote_patch_strip": 0
         }
       }
+    },
+    "pybind11_bazel@2.11.1": {
+      "name": "pybind11_bazel",
+      "version": "2.11.1",
+      "key": "pybind11_bazel@2.11.1",
+      "repoName": "pybind11_bazel",
+      "executionPlatformsToRegister": [],
+      "toolchainsToRegister": [],
+      "extensionUsages": [],
+      "deps": {
+        "platforms": "platforms@0.0.9",
+        "rules_cc": "rules_cc@0.0.9",
+        "bazel_tools": "bazel_tools@_",
+        "local_config_platform": "local_config_platform@_"
+      },
+      "repoSpec": {
+        "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+        "ruleClassName": "http_archive",
+        "attributes": {
+          "urls": [
+            "https://github.com/pybind/pybind11_bazel/releases/download/v2.11.1/pybind11_bazel-2.11.1.zip"
+          ],
+          "integrity": "sha256-LEZsmzzKeFK0fgeFADEomE/PDV1hoaLkxazu/ZNawiA=",
+          "strip_prefix": "pybind11_bazel-2.11.1",
+          "remote_patches": {},
+          "remote_patch_strip": 0
+        }
+      }
     }
   },
   "moduleExtensions": {
@@ -2949,7 +3012,7 @@
       "general": {
         "bzlTransitiveDigest": "iHLxWy9Kdma4o6vQG1U0vO82d7jPg9gng3gCoY4Dn88=",
         "recordedFileInputs": {
-          "@@//MODULE.bazel": "818d3d6a05f9446d49a9ca71484dc5d06317e39de0bfcf6580cdf260243c0150",
+          "@@//MODULE.bazel": "510c7c32da0bf633c73a9f30ce2e4cff965074f1a2134ffe8bd17612d5f621b6",
           "@@//src/test/tools/bzlmod/MODULE.bazel.lock": "4a9cf4d1d48d36a3d6e24a13094b2c32aa20be5a495d4e5b33e43db973250182"
         },
         "recordedDirentsInputs": {},
@@ -4485,6 +4548,41 @@
         "recordedRepoMappingEntries": []
       }
     },
+    "@@pybind11_bazel~//:python_configure.bzl%extension": {
+      "general": {
+        "bzlTransitiveDigest": "DJPCeiYqQS2i13szWN5NSI6sC6eaWgvECEyY/oNXWms=",
+        "recordedFileInputs": {
+          "@@pybind11_bazel~//MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e"
+        },
+        "recordedDirentsInputs": {},
+        "envVariables": {},
+        "generatedRepoSpecs": {
+          "local_config_python": {
+            "bzlFile": "@@pybind11_bazel~//:python_configure.bzl",
+            "ruleClassName": "python_configure",
+            "attributes": {}
+          },
+          "pybind11": {
+            "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl",
+            "ruleClassName": "http_archive",
+            "attributes": {
+              "build_file": "@@pybind11_bazel~//:pybind11.BUILD",
+              "strip_prefix": "pybind11-2.11.1",
+              "urls": [
+                "https://github.com/pybind/pybind11/archive/v2.11.1.zip"
+              ]
+            }
+          }
+        },
+        "recordedRepoMappingEntries": [
+          [
+            "pybind11_bazel~",
+            "bazel_tools",
+            "bazel_tools"
+          ]
+        ]
+      }
+    },
     "@@rules_go~//go:extensions.bzl%go_sdk": {
       "general": {
         "bzlTransitiveDigest": "k4MEsADgBfRC+sbMqB3lZL0JpdsCxlwSYO+z9zn9Y80=",
diff --git a/src/BUILD b/src/BUILD
index 8ae4ba4..efb330f 100644
--- a/src/BUILD
+++ b/src/BUILD
@@ -379,6 +379,7 @@
         "//src/tools/bzlmod:srcs",
         "//src/tools/execlog:srcs",
         "//src/tools/launcher:srcs",
+        "//src/tools/one_version:srcs",
         "//src/tools/remote:srcs",
         "//src/tools/singlejar:srcs",
         "//src/tools/starlark/java/com/google/devtools/starlark/common:srcs",
@@ -443,6 +444,7 @@
         "//src/java_tools/buildjar:srcs",
         "//src/java_tools/junitrunner:srcs",
         "//src/java_tools/singlejar:srcs",
+        "//src/tools/one_version:embedded_java_tools",
         "//src/tools/singlejar:embedded_java_tools",
         "//third_party/ijar:transitive_sources",
         "//third_party/java/jacoco:transitive_sources",
@@ -479,6 +481,7 @@
     visibility = ["//src/test/shell/bazel:__pkg__"],
     deps = [
         ":jars_java_tools_zip",
+        "//src/tools/one_version:one_version_transitive_zip",
         "//src/tools/singlejar:singlejar_transitive_zip",
         "//third_party/ijar:ijar_transitive_srcs_zip",
         "//third_party/java/jacoco:jacoco_jars_zip",
@@ -508,6 +511,7 @@
     visibility = ["//src/test/shell/bazel:__pkg__"],
     deps = [
         ":turbine_direct_graal_zip",
+        "//src/tools/one_version:one_version_deploy_zip",
         "//src/tools/singlejar:singlejar_deploy_zip",
         "//third_party/ijar:ijar_deploy_zip",
     ],
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java
index 85b814e..dd9291c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaOptions.java
@@ -398,8 +398,8 @@
       name = "experimental_one_version_enforcement",
       defaultValue = "OFF",
       converter = OneVersionEnforcementLevelConverter.class,
-      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
-      effectTags = {OptionEffectTag.UNKNOWN},
+      documentationCategory = OptionDocumentationCategory.INPUT_STRICTNESS,
+      effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS},
       help =
           "When enabled, enforce that a java_binary rule can't contain more than one version "
               + "of the same class file on the classpath. This enforcement can break the build, or "
@@ -420,8 +420,8 @@
   @Option(
       name = "one_version_enforcement_on_java_tests",
       defaultValue = "true",
-      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
-      effectTags = {OptionEffectTag.UNKNOWN},
+      documentationCategory = OptionDocumentationCategory.INPUT_STRICTNESS,
+      effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS},
       help =
           "When enabled, and with experimental_one_version_enforcement set to a non-NONE value,"
               + " enforce one version on java_test targets. This flag can be disabled to improve"
diff --git a/src/main/starlark/builtins_bzl/common/java/java_binary.bzl b/src/main/starlark/builtins_bzl/common/java/java_binary.bzl
index 06aa2ad..e42edae 100644
--- a/src/main/starlark/builtins_bzl/common/java/java_binary.bzl
+++ b/src/main/starlark/builtins_bzl/common/java/java_binary.bzl
@@ -341,7 +341,7 @@
     else:
         allowlist = helper.check_and_get_one_version_attribute(ctx, "_one_version_allowlist")
 
-    if not tool or not allowlist:  # On Mac oneversion tool is not available
+    if not tool:  # On Mac oneversion tool is not available
         return None
 
     output = ctx.actions.declare_file("%s-one-version.txt" % ctx.label.name)
@@ -349,8 +349,11 @@
     args = ctx.actions.args()
     args.set_param_file_format("shell").use_param_file("@%s", use_always = True)
 
+    one_version_inputs = []
     args.add("--output", output)
-    args.add("--whitelist", allowlist)
+    if allowlist:
+        args.add("--whitelist", allowlist)
+        one_version_inputs.append(allowlist)
     if one_version_level == "WARNING":
         args.add("--succeed_on_found_violations")
     args.add_all(
@@ -364,7 +367,7 @@
         progress_message = "Checking for one-version violations in %{label}",
         executable = tool,
         toolchain = semantics.JAVA_TOOLCHAIN_TYPE,
-        inputs = depset([allowlist], transitive = [inputs]),
+        inputs = depset(one_version_inputs, transitive = [inputs]),
         tools = [tool],
         outputs = [output],
         arguments = [args],
diff --git a/src/main/starlark/builtins_bzl/common/java/java_helper.bzl b/src/main/starlark/builtins_bzl/common/java/java_helper.bzl
index d91dc25..3b31e0c 100644
--- a/src/main/starlark/builtins_bzl/common/java/java_helper.bzl
+++ b/src/main/starlark/builtins_bzl/common/java/java_helper.bzl
@@ -201,7 +201,11 @@
     return value
 
 def _jar_and_target_arg_mapper(jar):
-    return jar.path + "," + str(jar.owner)
+    # Emit pretty labels for targets in the main repository.
+    label = str(jar.owner)
+    if label.startswith("@@//"):
+        label = label.lstrip("@")
+    return jar.path + "," + label
 
 def _get_feature_config(ctx):
     cc_toolchain = cc_helper.find_cpp_toolchain(ctx, mandatory = False)
diff --git a/src/test/shell/bazel/BUILD b/src/test/shell/bazel/BUILD
index 79c355f..83a27db 100644
--- a/src/test/shell/bazel/BUILD
+++ b/src/test/shell/bazel/BUILD
@@ -363,6 +363,9 @@
         "//src:java_tools_prebuilt.zip",
         "@bazel_tools//tools/bash/runfiles",
     ],
+    tags = [
+        "requires-network",  # For Bzlmod
+    ],
 )
 
 sh_test(
diff --git a/src/test/shell/bazel/bazel_java_test.sh b/src/test/shell/bazel/bazel_java_test.sh
index d19b27f..dbed869 100755
--- a/src/test/shell/bazel/bazel_java_test.sh
+++ b/src/test/shell/bazel/bazel_java_test.sh
@@ -88,6 +88,7 @@
 export TESTENV_DONT_BAZEL_CLEAN=1
 
 function tear_down() {
+  bazel shutdown
   rm -rf "$(bazel info bazel-bin)/java"
 }
 
@@ -1927,11 +1928,6 @@
 }
 
 function test_sandboxed_multiplexing() {
-  if [[ "${JAVA_TOOLS_ZIP}" == released ]]; then
-    # TODO: Enable test after the next java_tools release.
-    return 0
-  fi
-
   mkdir -p pkg
   cat << 'EOF' > pkg/BUILD
 load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain")
@@ -2084,4 +2080,104 @@
   expect_log "buildozer 'add deps @c//:c' //pkg:a"
 }
 
+function test_one_version() {
+  if [[ "${JAVA_TOOLS_ZIP}" == released ]]; then
+    # TODO: Enable test after the next java_tools release.
+    return 0
+  fi
+
+  # TODO: Remove patch on rules_java and add test for prebuilt tool after the next release.
+  cat << 'EOF' > MODULE.bazel
+bazel_dep(
+    name = "rules_java",
+    version = "7.5.0",
+)
+archive_override(
+    module_name = "rules_java",
+    urls = ["https://github.com/bazelbuild/rules_java/releases/download/7.5.0/rules_java-7.5.0.tar.gz"],
+    patches = ["//pkg:rules_java.patch"],
+)
+toolchains = use_extension("@rules_java//java:extensions.bzl", "toolchains")
+use_repo(toolchains, "remote_java_tools_linux")
+EOF
+
+  mkdir -p pkg
+  cat << 'EOF' > pkg/rules_java.patch
+--- MODULE.bazel
++++ MODULE.bazel
+@@ -13,6 +13,7 @@ bazel_dep(name = "bazel_skylib", version = "1.2.0")
+ # Required by @remote_java_tools, which is loaded via module extension.
+ bazel_dep(name = "rules_proto", version = "4.0.0")
+ bazel_dep(name = "rules_license", version = "0.0.3")
++bazel_dep(name = "abseil-cpp", version = "20240116.2", repo_name = "com_google_absl")
+
+ register_toolchains("//toolchains:all")
+
+EOF
+  cat << 'EOF' > pkg/BUILD
+load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain")
+
+default_java_toolchain(
+    name = "java_toolchain",
+    source_version = "17",
+    target_version = "17",
+    # TODO: Replace this with a target under @rules_java after the next release.
+    oneversion = "@remote_java_tools_linux//:prebuilt_one_version",
+)
+
+java_binary(
+    name = "a",
+    srcs = ["A.java"],
+    main_class = "A",
+    deps = [
+        "//pkg/b1",
+        "//pkg/b2",
+    ]
+)
+EOF
+  cat << 'EOF' > pkg/A.java
+public class A extends B {
+  public static void main(String[] args) {
+    System.err.println("Hello, two worlds!");
+  }
+}
+EOF
+  mkdir -p pkg/b1
+  cat << 'EOF' > pkg/b1/BUILD
+java_library(
+    name = "b1",
+    srcs = ["B.java"],
+    visibility = ["//visibility:public"],
+)
+EOF
+  cat << 'EOF' > pkg/b1/B.java
+public class B {
+  public void foo() {}
+}
+EOF
+  mkdir -p pkg/b2
+  cat << 'EOF' > pkg/b2/BUILD
+java_library(
+    name = "b2",
+    srcs = ["B.java"],
+    visibility = ["//visibility:public"],
+)
+EOF
+  cat << 'EOF' > pkg/b2/B.java
+public class B {
+  public void bar() {}
+}
+EOF
+
+  bazel build //pkg:a \
+    --java_language_version=17 \
+    --extra_toolchains=//pkg:java_toolchain_definition \
+    --experimental_one_version_enforcement=error \
+    >& $TEST_log && fail "build should have failed"
+  expect_log "Found one definition violations on the runtime classpath:"
+  expect_log "B has incompatible definitions in:"
+  expect_log " //pkg/b1:b1"
+  expect_log " //pkg/b2:b2"
+}
+
 run_suite "Java integration tests"
diff --git a/src/test/shell/bazel/bazel_java_tools_test.sh b/src/test/shell/bazel/bazel_java_tools_test.sh
index db8a364..25289a3 100755
--- a/src/test/shell/bazel/bazel_java_tools_test.sh
+++ b/src/test/shell/bazel/bazel_java_tools_test.sh
@@ -89,6 +89,9 @@
 )
 EOF
   cat $(rlocation io_bazel/src/tests/shell/bazel/rules_license_stanza.txt) >> WORKSPACE
+  cat > MODULE.bazel <<EOF
+bazel_dep(name = "abseil-cpp", version = "20240116.2", repo_name = "com_google_absl")
+EOF
 }
 
 function expect_path_in_java_tools() {
@@ -150,6 +153,12 @@
 
 function test_java_tools_has_turbine_direct() {
   expect_path_in_java_tools "java_tools/turbine_direct_binary_deploy.jar"
+  expect_path_in_java_tools_prebuilt "java_tools/turbine_direct_graal"
+}
+
+function test_java_tools_has_one_version() {
+  expect_path_in_java_tools "java_tools/src/tools/one_version"
+  expect_path_in_java_tools_prebuilt "java_tools/src/tools/one_version"
 }
 
 function test_java_tools_has_Runner() {
@@ -214,4 +223,17 @@
     @local_java_tools//:ijar_cc_binary || fail "ijar failed to build with layering check"
 }
 
+function test_java_tools_ijar_builds() {
+  bazel build @local_java_tools//:one_version_cc_bin || fail "one_version failed to build"
+}
+
+function test_java_tools_one_version_builds_with_layering_check() {
+  if [[ ! $(type -P clang) ]]; then
+    return
+  fi
+
+  bazel build --repo_env=CC=clang --features=layering_check \
+    @local_java_tools//:one_version_cc_bin || fail "one_version failed to build with layering check"
+}
+
 run_suite "Java tools archive tests"
diff --git a/src/tools/one_version/BUILD b/src/tools/one_version/BUILD
index a811bca..22a726d 100644
--- a/src/tools/one_version/BUILD
+++ b/src/tools/one_version/BUILD
@@ -1,7 +1,26 @@
+load("//src:release_archive.bzl", "release_archive")
+
 # Description:
 #   one version C++ implementation.
 package(default_visibility = ["//src:__subpackages__"])
 
+filegroup(
+    name = "srcs",
+    srcs = glob(["**"]),
+    visibility = ["//src:__pkg__"],
+)
+
+SOURCES = [
+    # keep sorted
+    "allowlist.cc",
+    "allowlist.h",
+    "duplicate_class_collector.cc",
+    "duplicate_class_collector.h",
+    "one_version.cc",
+    "one_version.h",
+    "one_version_main.cc",
+]
+
 cc_library(
     name = "duplicate_class_collector",
     srcs = [
@@ -12,6 +31,7 @@
     ],
     deps = [
         "@abseil-cpp//absl/container:flat_hash_map",
+        "@abseil-cpp//absl/strings",
     ],
 )
 
@@ -34,6 +54,8 @@
         ":duplicate_class_collector",
         "@abseil-cpp//absl/container:flat_hash_map",
         "@abseil-cpp//absl/container:flat_hash_set",
+        "@abseil-cpp//absl/strings",
+        "@abseil-cpp//absl/types:span",
     ],
 )
 
@@ -54,12 +76,12 @@
     srcs = ["one_version.cc"],
     hdrs = ["one_version.h"],
     deps = [
-        "//third_party/absl/log:die_if_null",
-        "//third_party/absl/memory",
-        "//third_party/absl/strings",
-        "//third_party/bazel/src/tools/one_version:allowlist",
-        "//third_party/bazel/src/tools/one_version:duplicate_class_collector",
-        "//third_party/bazel/src/tools/singlejar:input_jar",
+        ":allowlist",
+        ":duplicate_class_collector",
+        "//src/tools/singlejar:input_jar",
+        "@abseil-cpp//absl/log:die_if_null",
+        "@abseil-cpp//absl/memory",
+        "@abseil-cpp//absl/strings",
     ],
 )
 
@@ -68,16 +90,47 @@
     srcs = [
         "one_version_main.cc",
     ],
-    copts = ["-Ithird_party/bazel"],
     deps = [
         ":allowlist",
         ":duplicate_class_collector",
         ":one_version",
-        "//third_party/absl/container:flat_hash_map",
-        "//third_party/absl/container:flat_hash_set",
-        "//third_party/absl/log:die_if_null",
-        "//third_party/absl/strings",
-        "//third_party/bazel/src/tools/singlejar:input_jar",
-        "//third_party/bazel/src/tools/singlejar:token_stream",
+        "//src/tools/singlejar:input_jar",
+        "//src/tools/singlejar:token_stream",
+        "@abseil-cpp//absl/container:flat_hash_map",
+        "@abseil-cpp//absl/container:flat_hash_set",
+        "@abseil-cpp//absl/log:die_if_null",
+        "@abseil-cpp//absl/strings",
     ],
 )
+
+filegroup(
+    name = "embedded_java_tools",
+    srcs = SOURCES + [
+        "//src/tools/singlejar:embedded_java_tools",
+    ],
+    visibility = ["//src:__pkg__"],
+)
+
+release_archive(
+    name = "one_version_transitive_zip",
+    package_dir = "java_tools",
+    visibility = ["//src:__pkg__"],
+    deps = [
+        ":one_version_zip",
+        "//src/tools/singlejar:singlejar_transitive_zip",
+    ],
+)
+
+release_archive(
+    name = "one_version_zip",
+    srcs = SOURCES,
+    package_dir = "src/tools/one_version",
+    visibility = ["//visibility:private"],
+)
+
+release_archive(
+    name = "one_version_deploy_zip",
+    srcs = [":one_version_main"],
+    package_dir = "java_tools/src/tools/one_version",
+    visibility = ["//src:__pkg__"],
+)
diff --git a/src/tools/singlejar/BUILD b/src/tools/singlejar/BUILD
index 9d17622..595e3b3 100644
--- a/src/tools/singlejar/BUILD
+++ b/src/tools/singlejar/BUILD
@@ -40,13 +40,19 @@
         "//src/main/protobuf:desugar_deps_filegroup",
         "//third_party/zlib:embedded_tools",
     ],
-    visibility = ["//src:__pkg__"],
+    visibility = [
+        "//src:__pkg__",
+        "//src/tools/one_version:__pkg__",
+    ],
 )
 
 release_archive(
     name = "singlejar_transitive_zip",
     package_dir = "java_tools",
-    visibility = ["//src:__pkg__"],
+    visibility = [
+        "//src:__pkg__",
+        "//src/tools/one_version:__pkg__",
+    ],
     deps = [
         ":singlejar_zip",
         "//src:zlib_zip",
diff --git a/tools/jdk/BUILD.java_tools b/tools/jdk/BUILD.java_tools
index cf54be1..aa6b15b 100644
--- a/tools/jdk/BUILD.java_tools
+++ b/tools/jdk/BUILD.java_tools
@@ -584,3 +584,82 @@
     visibility = ["//visibility:public"],
     runtime_deps = [":proguard_import"],
 )
+
+##################### one_version
+
+# See comment for ":ijar_cc_binary_main".
+cc_library(
+    name = "one_version_cc_bin_main",
+    srcs = [
+        "java_tools/src/tools/one_version/one_version_main.cc",
+    ],
+    copts = SUPRESSED_WARNINGS,
+    linkopts = select({
+        ":freebsd": ["-lm"],
+        ":openbsd": ["-lm"],
+        "//conditions:default": [],
+    }),
+    linkstatic = 1, # provides main()
+    deps = [
+        ":allowlist",
+        ":duplicate_class_collector",
+        ":one_version",
+        ":input_jar",
+        ":token_stream",
+        "@com_google_absl//absl/container:flat_hash_map",
+        "@com_google_absl//absl/container:flat_hash_set",
+        "@com_google_absl//absl/log:die_if_null",
+        "@com_google_absl//absl/strings",
+    ],
+    alwayslink = 1,
+)
+
+cc_binary(
+    name = "one_version_cc_bin",
+    visibility = ["//visibility:public"],
+    linkstatic = 1,
+    deps = [":one_version_cc_bin_main"],
+)
+
+cc_library(
+    name = "duplicate_class_collector",
+    srcs = ["java_tools/src/tools/one_version/duplicate_class_collector.cc"],
+    hdrs = ["java_tools/src/tools/one_version/duplicate_class_collector.h"],
+    copts = SUPRESSED_WARNINGS,
+    strip_include_prefix = "java_tools",
+    deps = [
+        "@com_google_absl//absl/container:flat_hash_map",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "allowlist",
+    srcs = ["java_tools/src/tools/one_version/allowlist.cc"],
+    hdrs = ["java_tools/src/tools/one_version/allowlist.h"],
+    copts = SUPRESSED_WARNINGS,
+    strip_include_prefix = "java_tools",
+    deps = [
+        ":duplicate_class_collector",
+        "@com_google_absl//absl/container:flat_hash_map",
+        "@com_google_absl//absl/container:flat_hash_set",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/types:span",
+    ],
+)
+
+cc_library(
+    name = "one_version",
+    srcs = ["java_tools/src/tools/one_version/one_version.cc"],
+    hdrs = ["java_tools/src/tools/one_version/one_version.h"],
+    copts = SUPRESSED_WARNINGS,
+    strip_include_prefix = "java_tools",
+    deps = [
+        ":allowlist",
+        ":duplicate_class_collector",
+        ":input_jar",
+        "@com_google_absl//absl/log:die_if_null",
+        "@com_google_absl//absl/memory",
+        "@com_google_absl//absl/strings",
+    ],
+)
diff --git a/tools/jdk/BUILD.java_tools_prebuilt b/tools/jdk/BUILD.java_tools_prebuilt
index fcc97ff..2401bd9 100644
--- a/tools/jdk/BUILD.java_tools_prebuilt
+++ b/tools/jdk/BUILD.java_tools_prebuilt
@@ -8,6 +8,14 @@
 )
 
 filegroup(
+    name = "prebuilt_one_version",
+    srcs = select({
+        ":windows": ["java_tools/src/tools/one_version/one_version_main.exe"],
+        "//conditions:default": ["java_tools/src/tools/one_version/one_version_main"],
+    }),
+)
+
+filegroup(
     name = "prebuilt_singlejar",
     srcs = select({
         ":windows": ["java_tools/src/tools/singlejar/singlejar_local.exe"],