Skip to content

Commit 009f97d

Browse files
authoredMar 25, 2025··
Merge pull request #88 from lucidsoftware/java-stub-workaround
Use custom version of java_stub_template to avoid orphaned processes
2 parents 9d784a7 + 4349664 commit 009f97d

File tree

5 files changed

+307
-21
lines changed

5 files changed

+307
-21
lines changed
 

‎MODULE.bazel

-19
Original file line numberDiff line numberDiff line change
@@ -124,22 +124,3 @@ annex_proto.install(
124124
],
125125
)
126126
use_repo(annex_proto, "annex_proto")
127-
128-
java_launcher_version = "8.9.0"
129-
130-
java_launcher_template_sha = "289d8c13a3e2680bfbe21a2c6a57cc428ecdc6a0f2c04bda4d4dc2da40311eaa"
131-
132-
java_stub_template_url = (
133-
"raw.githubusercontent.com/bazelbuild/rules_java/" +
134-
java_launcher_version +
135-
"/java/bazel/rules/" +
136-
"java_stub_template.txt"
137-
)
138-
139-
http_file = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
140-
141-
http_file(
142-
name = "anx_java_stub_template",
143-
sha256 = java_launcher_template_sha,
144-
urls = ["https://%s" % java_stub_template_url],
145-
)

‎docs/scala.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ e.g. ScalaTest, specs2, ScalaCheck, utest.
6262
* example: `my.package.MyTest`
6363
* example: `my.package.MyTest#some test name here` (remember to escape the whitespace)
6464

65-
* [java_stub_template](https://github.com/bazelbuild/bazel/blob/0.27.0/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt) options.
65+
* [java_stub_template](https://github.com/bazelbuild/rules_java/blob/8.11.0/java/bazel/rules/java_stub_template.txt) options.
6666

6767
* Additional options: ANSI color codes and verbosity
6868

‎rules/scala.bzl

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ _runtime_private_attributes = {
181181
),
182182
"_java_stub_template": attr.label(
183183
cfg = _scala_outgoing_transition,
184-
default = Label("@anx_java_stub_template//file"),
184+
default = Label("//third_party/java_stub_template:java_stub_template.txt"),
185185
allow_single_file = True,
186186
),
187187
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# We use a custom java_stub_template in this ruleset because of this bazel
2+
# issue: https://github.com/bazelbuild/bazel/issues/19036
3+
# Once Bazel drops Java 8 support, this will be easier to resolve upstream.
4+
# If someone wants to fix it upstream before then, go nuts.
5+
exports_files(["java_stub_template.txt"])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
#!/usr/bin/env bash
2+
# Copyright 2014 The Bazel Authors. All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
# This script was generated from java_stub_template.txt. Please
17+
# don't edit it directly.
18+
#
19+
# If present, these flags should either be at the beginning of the command
20+
# line, or they should be wrapped in a --wrapper_script_flag=FLAG argument.
21+
#
22+
# --debug Launch the JVM in remote debugging mode listening
23+
# --debug=<port> to the specified port or the port set in the
24+
# DEFAULT_JVM_DEBUG_PORT environment variable (e.g.
25+
# 'export DEFAULT_JVM_DEBUG_PORT=8000') or else the
26+
# default port of 5005. The JVM starts suspended
27+
# unless the DEFAULT_JVM_DEBUG_SUSPEND environment
28+
# variable is set to 'n'.
29+
# --main_advice=<class> Run an alternate main class with the usual main
30+
# program and arguments appended as arguments.
31+
# --main_advice_classpath=<classpath>
32+
# Prepend additional class path entries.
33+
# --jvm_flag=<flag> Pass <flag> to the "java" command itself.
34+
# <flag> may contain spaces. Can be used multiple times.
35+
# --jvm_flags=<flags> Pass space-separated flags to the "java" command
36+
# itself. Can be used multiple times.
37+
# --singlejar Start the program from the packed-up deployment
38+
# jar rather than from the classpath.
39+
# --print_javabin Print the location of java executable binary and exit.
40+
# --classpath_limit=<length>
41+
# Specify the maximum classpath length. If the classpath
42+
# is shorter, this script passes it to Java as a command
43+
# line flag, otherwise it creates a classpath jar.
44+
#
45+
# The remainder of the command line is passed to the program.
46+
47+
# Make it easy to insert 'set -x' or similar commands when debugging problems with this script.
48+
eval "$JAVA_STUB_DEBUG"
49+
50+
# Prevent problems where the caller has exported CLASSPATH, causing our
51+
# computed value to be copied into the environment and double-counted
52+
# against the argv limit.
53+
unset CLASSPATH
54+
55+
JVM_FLAGS_CMDLINE=()
56+
57+
# Processes an argument for the wrapper. Returns 0 if the given argument
58+
# was recognized as an argument for this wrapper, and 1 if it was not.
59+
function process_wrapper_argument() {
60+
case "$1" in
61+
--debug) JVM_DEBUG_PORT="${DEFAULT_JVM_DEBUG_PORT:-5005}" ;;
62+
--debug=*) JVM_DEBUG_PORT="${1#--debug=}" ;;
63+
--main_advice=*) MAIN_ADVICE="${1#--main_advice=}" ;;
64+
--main_advice_classpath=*) MAIN_ADVICE_CLASSPATH="${1#--main_advice_classpath=}" ;;
65+
--jvm_flag=*) JVM_FLAGS_CMDLINE+=("${1#--jvm_flag=}") ;;
66+
--jvm_flags=*) JVM_FLAGS_CMDLINE+=(${1#--jvm_flags=}) ;;
67+
--singlejar) SINGLEJAR=1 ;;
68+
--print_javabin) PRINT_JAVABIN=1 ;;
69+
--classpath_limit=*)
70+
CLASSPATH_LIMIT="${1#--classpath_limit=}"
71+
echo "$CLASSPATH_LIMIT" | grep -q '^[0-9]\+$' ||
72+
die "ERROR: $self failed, --classpath_limit is not a number"
73+
;;
74+
*)
75+
return 1
76+
;;
77+
esac
78+
return 0
79+
}
80+
81+
die() {
82+
printf "%s: $1\n" "$0" "${@:2}" >&2
83+
exit 1
84+
}
85+
86+
# Windows
87+
function is_windows() {
88+
[[ "${OSTYPE}" =~ msys* ]] || [[ "${OSTYPE}" =~ cygwin* ]]
89+
}
90+
91+
# macOS
92+
function is_macos() {
93+
[[ "${OSTYPE}" =~ darwin* ]]
94+
}
95+
96+
# Parse arguments sequentially until the first unrecognized arg is encountered.
97+
# Scan the remaining args for --wrapper_script_flag=X options and process them.
98+
ARGS=()
99+
for ARG in "$@"; do
100+
if [[ "$ARG" == --wrapper_script_flag=* ]]; then
101+
process_wrapper_argument "${ARG#--wrapper_script_flag=}" ||
102+
die "invalid wrapper argument '%s'" "$ARG"
103+
elif [[ "${#ARGS}" -gt 0 ]] || ! process_wrapper_argument "$ARG"; then
104+
ARGS+=("$ARG")
105+
fi
106+
done
107+
108+
# A file storing the test's runtime classpath, excluding the test support.
109+
# The file is read by the persistent test runner. The jars inside the file are
110+
# loaded dynamically for every test run into a custom classloader.
111+
%test_runtime_classpath_file%
112+
113+
# Find our runfiles tree. We need this to construct the classpath
114+
# (unless --singlejar was passed).
115+
#
116+
# Call this program X. X was generated by a java_binary or java_test rule.
117+
# X may be invoked in many ways:
118+
# 1a) directly by a user, with $0 in the output tree
119+
# 1b) via 'bazel run' (similar to case 1a)
120+
# 2) directly by a user, with $0 in X's runfiles tree
121+
# 3) by another program Y which has a data dependency on X, with $0 in Y's runfiles tree
122+
# 4) via 'bazel test'
123+
# 5) by a genrule cmd, with $0 in the output tree
124+
# 6) case 3 in the context of a genrule
125+
#
126+
# For case 1, $0 will be a regular file, and the runfiles tree will be
127+
# at $0.runfiles.
128+
# For case 2, $0 will be a symlink to the file seen in case 1.
129+
# For case 3, we use Y's runfiles tree, which will be a superset of X's.
130+
# For case 4, $JAVA_RUNFILES and $TEST_SRCDIR should already be set.
131+
# Case 5 is handled like case 1.
132+
# Case 6 is handled like case 3.
133+
134+
# If we are running on Windows, convert the windows style path
135+
# to unix style for detecting runfiles path.
136+
if is_windows; then
137+
self=$(cygpath --unix "$0")
138+
else
139+
self="$0"
140+
fi
141+
142+
if [[ "$self" != /* ]]; then
143+
self="$PWD/$self"
144+
fi
145+
146+
if [[ "$SINGLEJAR" != 1 || "%needs_runfiles%" == 1 ]]; then
147+
if [[ -z "$JAVA_RUNFILES" ]]; then
148+
while true; do
149+
if [[ -e "$self.runfiles" ]]; then
150+
JAVA_RUNFILES="$self.runfiles"
151+
break
152+
fi
153+
if [[ $self == *.runfiles/* ]]; then
154+
JAVA_RUNFILES="${self%.runfiles/*}.runfiles"
155+
break
156+
fi
157+
if [[ ! -L "$self" ]]; then
158+
break
159+
fi
160+
readlink="$(readlink "$self")"
161+
if [[ "$readlink" = /* ]]; then
162+
self="$readlink"
163+
else
164+
# resolve relative symlink
165+
self="${self%/*}/$readlink"
166+
fi
167+
done
168+
if [[ -n "$JAVA_RUNFILES" ]]; then
169+
export TEST_SRCDIR=${TEST_SRCDIR:-$JAVA_RUNFILES}
170+
elif [[ -f "${self}_deploy.jar" && "%needs_runfiles%" == 0 ]]; then
171+
SINGLEJAR=1
172+
else
173+
die 'Cannot locate runfiles directory. (Set $JAVA_RUNFILES to inhibit searching.)'
174+
fi
175+
fi
176+
fi
177+
178+
# If we are running on Windows, we need a windows style runfiles path for constructing CLASSPATH
179+
if is_windows; then
180+
JAVA_RUNFILES=$(cygpath --windows "$JAVA_RUNFILES")
181+
fi
182+
183+
export JAVA_RUNFILES
184+
export RUNFILES_MANIFEST_FILE="${JAVA_RUNFILES}/MANIFEST"
185+
export RUNFILES_MANIFEST_ONLY=%runfiles_manifest_only%
186+
187+
if [ -z "$RUNFILES_MANIFEST_ONLY" ]; then
188+
function rlocation() {
189+
if [[ "$1" = /* ]]; then
190+
echo $1
191+
else
192+
echo "$(dirname $RUNFILES_MANIFEST_FILE)/$1"
193+
fi
194+
}
195+
else
196+
if ! is_macos; then
197+
# Read file into my_array
198+
oifs=$IFS
199+
IFS=$'\n'
200+
my_array=($(sed -e 's/\r//g' "$RUNFILES_MANIFEST_FILE"))
201+
IFS=$oifs
202+
203+
# Process each runfile line into a [key,value] entry in runfiles_array
204+
# declare -A is not supported on macOS because an old version of bash is used.
205+
declare -A runfiles_array
206+
for line in "${my_array[@]}"; do
207+
line_split=($line)
208+
runfiles_array[${line_split[0]}]=${line_split[@]:1}
209+
done
210+
fi
211+
212+
function rlocation() {
213+
if [[ "$1" = /* ]]; then
214+
echo $1
215+
else
216+
if is_macos; then
217+
# Print the rest of line after the first space
218+
# First, set the first column to empty and print rest of the line
219+
# Second, use a trick of awk to remove leading and trailing spaces.
220+
echo $(grep "^$1 " $RUNFILES_MANIFEST_FILE | awk '{ $1=""; print }' | awk '{ $1=$1; print }')
221+
else
222+
echo ${runfiles_array[$1]}
223+
fi
224+
fi
225+
}
226+
fi
227+
228+
# Set JAVABIN to the path to the JVM launcher.
229+
%javabin%
230+
231+
if [[ "$PRINT_JAVABIN" == 1 || "%java_start_class%" == "--print_javabin" ]]; then
232+
echo -n "$JAVABIN"
233+
exit 0
234+
fi
235+
236+
if [[ "$SINGLEJAR" == 1 ]]; then
237+
CLASSPATH="${self}_deploy.jar"
238+
# Check for the deploy jar now. If it doesn't exist, we can print a
239+
# more helpful error message than the JVM.
240+
[[ -r "$CLASSPATH" ]] ||
241+
die "Option --singlejar was passed, but %s does not exist.\n (You may need to build it explicitly.)" "$CLASSPATH"
242+
else
243+
# Create the shortest classpath we can, by making it relative if possible.
244+
RUNPATH="${JAVA_RUNFILES}/%workspace_prefix%"
245+
RUNPATH="${RUNPATH#$PWD/}"
246+
CLASSPATH=%classpath%
247+
fi
248+
249+
# Export the locations which will be used to find the location of the classes from the classpath file.
250+
export SELF_LOCATION="$self"
251+
export CLASSLOADER_PREFIX_PATH="${RUNPATH}"
252+
253+
# If using Jacoco in offline instrumentation mode, the CLASSPATH contains instrumented files.
254+
# We need to make the metadata jar with uninstrumented classes available for generating
255+
# the lcov-compatible coverage report, and we don't want it on the classpath.
256+
%set_jacoco_metadata%
257+
%set_jacoco_main_class%
258+
%set_jacoco_java_runfiles_root%
259+
export JACOCO_IS_JAR_WRAPPED=0
260+
261+
if [[ -n "$JVM_DEBUG_PORT" ]]; then
262+
JVM_DEBUG_SUSPEND=${DEFAULT_JVM_DEBUG_SUSPEND:-"y"}
263+
JVM_DEBUG_FLAGS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=${JVM_DEBUG_SUSPEND},address=${JVM_DEBUG_PORT}"
264+
265+
if [[ "$PERSISTENT_TEST_RUNNER" == "true" ]]; then
266+
JVM_DEBUG_FLAGS+=",quiet=y"
267+
fi
268+
fi
269+
270+
if [[ -n "$MAIN_ADVICE_CLASSPATH" ]]; then
271+
CLASSPATH="${MAIN_ADVICE_CLASSPATH}:${CLASSPATH}"
272+
fi
273+
274+
# Check if TEST_TMPDIR is available to use for scratch.
275+
if [[ -n "$TEST_TMPDIR" && -d "$TEST_TMPDIR" ]]; then
276+
JVM_FLAGS+=" -Djava.io.tmpdir=$TEST_TMPDIR"
277+
fi
278+
279+
ARGS=(
280+
${JVM_DEBUG_FLAGS}
281+
${JVM_FLAGS}
282+
%jvm_flags%
283+
"${JVM_FLAGS_CMDLINE[@]}"
284+
${MAIN_ADVICE}
285+
%java_start_class%
286+
"${ARGS[@]}")
287+
288+
# If the user didn't specify a --classpath_limit, use the default value.
289+
if [ -z "$CLASSPATH_LIMIT" ]; then
290+
# Windows per-arg limit MAX_ARG_STRLEN == 8k
291+
# Linux per-arg limit MAX_ARG_STRLEN == 128k
292+
is_windows && CLASSPATH_LIMIT=7000 || CLASSPATH_LIMIT=120000
293+
fi
294+
295+
if (("${#CLASSPATH}" > ${CLASSPATH_LIMIT})); then
296+
# @argfile syntax is only supported by Java 9+
297+
exec $JAVABIN -classpath @<(echo "$CLASSPATH") "${ARGS[@]}"
298+
else
299+
exec $JAVABIN -classpath $CLASSPATH "${ARGS[@]}"
300+
fi

0 commit comments

Comments
 (0)
Please sign in to comment.