From 68de125b50a1c50a609c08992814837608c9f8ab Mon Sep 17 00:00:00 2001 From: David Ostrovsky Date: Sun, 16 Aug 2026 21:36:13 +0200 Subject: [PATCH] Silence protobuf Unsafe warnings from Java TurbineDirect TurbineDirect bundles protobuf, whose UnsafeUtil calls terminally-deprecated sun.misc.Unsafe methods. On JDK 24+ (JEP 498), the JVM prints a warning for each such call during header compilation: WARNING: A terminally deprecated method in sun.misc.Unsafe has been called WARNING: sun.misc.Unsafe::arrayBaseOffset has been called by com.google.protobuf.UnsafeUtil The direct header compiler has two invocation shapes. The Java TurbineDirect launcher runs as java -jar, but the prebuilt `turbine_direct_graal` tools are native binaries. Only the Java launcher can receive JVM options; the native binary parses the same values as Turbine CLI options and fails with: unknown option: --sun-misc-unsafe-memory-access=allow Add --sun-misc-unsafe-memory-access=allow only when the selected direct header compiler is packaged as a deploy jar and the Java runtime feature version is 24 or newer. This silences the protobuf warning for the Java launcher without breaking the Graal/native path. Add analysis tests for the three relevant cases: JDK 24 plus a jar direct compiler gets the flag, JDK 23 plus a jar direct compiler does not, and JDK 24 plus a native direct compiler does not. See https://github.com/protocolbuffers/protobuf/issues/20760. Closes #374 Tested: * buildifier java/common/rules/java_toolchain.bzl \ test/java/toolchains/java_toolchain_tests.bzl * bazelisk test //test/java/toolchains:java_toolchain_tests \ --test_output=errors --- java/common/rules/java_toolchain.bzl | 28 +++++ test/java/toolchains/java_toolchain_tests.bzl | 114 ++++++++++++++++++ 2 files changed, 142 insertions(+) diff --git a/java/common/rules/java_toolchain.bzl b/java/common/rules/java_toolchain.bzl index a24ae4f1..ff0a9a6d 100644 --- a/java/common/rules/java_toolchain.bzl +++ b/java/common/rules/java_toolchain.bzl @@ -91,6 +91,23 @@ def _java_toolchain_impl(ctx): else: header_compiler_direct_data = [] header_compiler_direct_jvm_opts = [] + + # protocolbuffers/protobuf#20760: Turbine's bundled protobuf (UnsafeUtil) + # calls terminally-deprecated sun.misc.Unsafe methods, which the JVM warns + # about on JDK 24+ (JEP 498). The Java TurbineDirect launcher does + # not receive turbine_jvm_opts, so those warnings cannot otherwise be + # silenced for the direct header compiler. Do not pass this JVM-only + # flag to turbine_direct_graal: its native binary parses these values + # as Turbine command-line options. + if ( + java_runtime and + java_runtime.version >= 24 and + _is_java_launcher_tool(ctx.attr.header_compiler_direct) + ): + header_compiler_direct_jvm_opts = header_compiler_direct_jvm_opts + [ + "--sun-misc-unsafe-memory-access=allow", + ] + if ctx.attr.oneversion_allowlist and ctx.attr.oneversion_whitelist: fail("oneversion_allowlist and oneversion_whitelist are mutually exclusive") oneversion_allowlist = ctx.file.oneversion_allowlist if ctx.file.oneversion_allowlist else ctx.file.oneversion_whitelist @@ -156,6 +173,17 @@ def _get_java_runtime(ctx): return None return ctx.attr.java_runtime[ToolchainInfo].java_runtime +def _is_java_launcher_tool(tool): + """Returns whether tool is packaged as a deploy jar run by java -jar. + + Native tools such as turbine_direct_graal receive these values as tool + command-line options, not JVM options. + """ + if not tool: + return False + executable = tool[DefaultInfo].files_to_run.executable + return executable and executable.extension == "jar" + def _get_javac_opts(ctx): opts = [] if ctx.attr.source_version: diff --git a/test/java/toolchains/java_toolchain_tests.bzl b/test/java/toolchains/java_toolchain_tests.bzl index 793de8ea..a7230428 100644 --- a/test/java/toolchains/java_toolchain_tests.bzl +++ b/test/java/toolchains/java_toolchain_tests.bzl @@ -7,6 +7,7 @@ load("//java:java_binary.bzl", "java_binary") load("//java:java_library.bzl", "java_library") load("//java:java_plugin.bzl", "java_plugin") load("//java/common:java_common.bzl", "java_common") +load("//java/toolchains:java_runtime.bzl", "java_runtime") load("//test/java/testutil:java_info_subject.bzl", "java_info_subject") load("//test/java/testutil:java_toolchain_info_subject.bzl", "java_toolchain_info_subject") load("//test/java/testutil:javac_action_subject.bzl", "javac_action_subject") @@ -560,6 +561,116 @@ def _test_java_compile_action_uses_tool_specific_jvm_opts_impl(env, target): header_action = env.expect.that_target(target).action_generating("{package}/lib{name}-hjar.jar") header_action.argv().contains("-DturbineFlag=1") +_UNSAFE_MEMORY_ACCESS_OPT = "--sun-misc-unsafe-memory-access=allow" + +def _test_jdk24_unsafe_opt_for_java_direct_header_compiler(name): + util.helper_target( + java_runtime, + name = name + "/jdk24", + version = 24, + ) + util.helper_target( + mock_java_toolchain, + name = name + "/java_toolchain", + header_compiler_direct = name + "/turbine_direct.jar", + java_runtime = name + "/jdk24", + ) + util.helper_target( + java_library, + name = name + "/java_lib", + srcs = ["a.java"], + ) + + analysis_test( + name = name, + impl = _test_jdk24_unsafe_opt_for_java_direct_header_compiler_impl, + target = name + "/java_lib", + config_settings = { + "//command_line_option:java_header_compilation": "true", + "//command_line_option:extra_toolchains": [Label(name + "/java_toolchain")], + }, + ) + +def _test_jdk24_unsafe_opt_for_java_direct_header_compiler_impl(env, target): + header_action = env.expect.that_target(target).action_generating( + "{package}/lib{name}-hjar.jar", + ) + + header_action.argv().contains("{package}/{test_name}/turbine_direct.jar") + header_action.argv().contains(_UNSAFE_MEMORY_ACCESS_OPT) + +def _test_no_jdk23_unsafe_opt_for_java_direct_header_compiler(name): + util.helper_target( + java_runtime, + name = name + "/jdk23", + version = 23, + ) + util.helper_target( + mock_java_toolchain, + name = name + "/toolchain", + header_compiler_direct = name + "/turbine_direct.jar", + java_runtime = name + "/jdk23", + ) + util.helper_target( + java_library, + name = name + "/lib", + srcs = ["a.java"], + ) + + analysis_test( + name = name, + impl = _test_no_jdk23_unsafe_opt_for_java_direct_header_compiler_impl, + target = name + "/lib", + config_settings = { + "//command_line_option:java_header_compilation": "true", + "//command_line_option:extra_toolchains": [Label(name + "/toolchain")], + }, + ) + +def _test_no_jdk23_unsafe_opt_for_java_direct_header_compiler_impl(env, target): + header_action = env.expect.that_target(target).action_generating( + "{package}/lib{name}-hjar.jar", + ) + + header_action.argv().contains("{package}/{test_name}/turbine_direct.jar") + header_action.argv().not_contains(_UNSAFE_MEMORY_ACCESS_OPT) + +def _test_no_jdk24_unsafe_opt_for_native_direct_header_compiler(name): + util.helper_target( + java_runtime, + name = name + "/jdk24", + version = 24, + ) + util.helper_target( + mock_java_toolchain, + name = name + "/native_toolchain", + header_compiler_direct = name + "/turbine_direct_graal", + java_runtime = name + "/jdk24", + ) + util.helper_target( + java_library, + name = name + "/native_lib", + srcs = ["b.java"], + ) + + analysis_test( + name = name, + impl = _test_no_jdk24_unsafe_opt_for_native_direct_header_compiler_impl, + target = name + "/native_lib", + config_settings = { + "//command_line_option:java_header_compilation": "true", + "//command_line_option:extra_toolchains": [Label(name + "/native_toolchain")], + }, + ) + +def _test_no_jdk24_unsafe_opt_for_native_direct_header_compiler_impl(env, target): + header_action = env.expect.that_target(target).action_generating( + "{package}/lib{name}-hjar.jar", + ) + + header_action.argv().contains("{package}/{test_name}/turbine_direct_graal") + header_action.argv().not_contains(_UNSAFE_MEMORY_ACCESS_OPT) + def _test_javabuilder_location_expansion_with_multiple_artifacts(name): util.helper_target( native.filegroup, @@ -766,6 +877,9 @@ def java_toolchain_tests(name): _test_java_compile_action_target_gets_javacopts_from_toolchain, _test_java_compile_action_exec_gets_javacopts_from_toolchain, _test_java_compile_action_uses_tool_specific_jvm_opts, + _test_jdk24_unsafe_opt_for_java_direct_header_compiler, + _test_no_jdk23_unsafe_opt_for_java_direct_header_compiler, + _test_no_jdk24_unsafe_opt_for_native_direct_header_compiler, _test_javabuilder_location_expansion_with_multiple_artifacts, _test_java_common_without_toolchain_type_fails, _test_java_toolchain_flag_default,