This is an automated email from the ASF dual-hosted git repository.

bobbai00 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git


The following commit(s) were added to refs/heads/main by this push:
     new 75ff07e36a feat(build): bump Scala/Java services to Java 17 LTS (#4938)
75ff07e36a is described below

commit 75ff07e36adcc626a91a41f96b78893e2d5e63c3
Author: Jiadong Bai <[email protected]>
AuthorDate: Fri May 8 21:51:40 2026 -0700

    feat(build): bump Scala/Java services to Java 17 LTS (#4938)
    
    ### What changes were proposed in this PR?
    
    Bump all Scala/Java microservices from Java 11 to Java 17 LTS, and
    centralize the JDK 17 `--add-opens` flags through `.jvmopts` as a
    single source of truth.
    
    **Toolchain bumps**
    
    - 8 Dockerfiles under `bin/`: build base
      `sbtscala/scala-sbt:eclipse-temurin-jammy-11.0.17_8_1.9.3_2.13.11`
      → `...-17.0.5_8_1.9.3_2.13.11` (same sbt 1.9.3 + Scala 2.13.11);
      runtime `eclipse-temurin:11-{jdk,jre}-jammy` → `17-{jdk,jre}-jammy`.
    - `.github/workflows/build.yml` and `build-and-push-images.yml`:
      `java-version: 11` → `17` (matrix entries + 5 `setup-java` steps).
    - `AGENTS.md`: toolchain table.
    
    **`.jvmopts` as single source of truth**
    
    `.jvmopts` lists the seven `--add-opens` flags JDK 17 needs for the
    runtime (Pekko, Apache Arrow, Ehcache `SizeOf`, Pekko Kryo
    serialization). The same file reaches every JVM the build launches:
    
    - sbt's own JVM: sbt's launcher reads `.jvmopts` directly.
    - forked test JVMs (sbt-jacoco): `ThisBuild / Test / javaOptions ++=
      JdkOptions.jvmFlags(...)` in `build.sbt`.
    - sbt-native-packager `bin/<svc>` launchers in production dists:
      `Universal / javaOptions ++= JdkOptions.jvmFlags(...).map("-J" + _)`,
      bundled per-project via `asfLicensingSettings` (Universal does not
      cascade from ThisBuild).
    - IntelliJ run configs `.run/ComputingUnit{Master,Worker}.run.xml`:
      `VM_PARAMETERS=@$PROJECT_DIR$/.jvmopts` (JDK 9+ argfile expansion).
    
    `project/JdkOptions.scala` (modeled on Pekko's) reads the file once
    and exposes a `Seq[String]` for the build to wire up.
    
    ### Any related issues, documentation, discussions?
    
    Closes #4937. Refs discussion #4001.
    
    ### How was this PR tested?
    
    CI's amber job now finishes in
    single-digit minutes, with all 5 `jacoco` tasks passing. Local
    verification: `sbt show ThisBuild / Test / javaOptions` and
    `sbt show <project> / Universal / javaOptions` confirm flag
    propagation across all subprojects; `java @.jvmopts -version`
    confirms the JDK accepts the argfile cleanly; running amber
    `jacoco` locally hits zero `InaccessibleObjectException`.
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Code (Opus 4.7)
    
    ---------
    
    Co-authored-by: Xinyuan Lin <[email protected]>
    Co-authored-by: Bot Bai <[email protected]>
    Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
---
 .github/workflows/build-and-push-images.yml        |  6 +--
 .github/workflows/build.yml                        | 10 ++--
 .jvmopts                                           | 28 +++++++++++
 .run/ComputingUnitMaster.run.xml                   |  1 +
 .run/ComputingUnitWorker.run.xml                   |  1 +
 AGENTS.md                                          | 12 ++++-
 bin/access-control-service.dockerfile              |  5 +-
 bin/computing-unit-master.dockerfile               |  5 +-
 bin/computing-unit-worker.dockerfile               |  5 +-
 bin/config-service.dockerfile                      |  5 +-
 bin/file-service.dockerfile                        |  5 +-
 bin/texera-web-application.dockerfile              |  5 +-
 bin/workflow-compiling-service.dockerfile          |  5 +-
 ...flow-computing-unit-managing-service.dockerfile |  5 +-
 build.sbt                                          | 14 +++++-
 project/JdkOptions.scala                           | 57 ++++++++++++++++++++++
 16 files changed, 142 insertions(+), 27 deletions(-)

diff --git a/.github/workflows/build-and-push-images.yml 
b/.github/workflows/build-and-push-images.yml
index 19534787f8..ae998c9a9e 100644
--- a/.github/workflows/build-and-push-images.yml
+++ b/.github/workflows/build-and-push-images.yml
@@ -123,7 +123,7 @@ jobs:
         uses: actions/setup-java@v5
         with:
           distribution: 'temurin'
-          java-version: 11
+          java-version: 17
 
       - name: Setup sbt launcher
         uses: sbt/setup-sbt@508b753e53cb6095967669e0911487d2b9bc9f41 # v1.1.22
@@ -325,7 +325,7 @@ jobs:
         uses: actions/setup-java@v5
         with:
           distribution: 'temurin'
-          java-version: 11
+          java-version: 17
 
       - name: Setup sbt launcher
         uses: sbt/setup-sbt@508b753e53cb6095967669e0911487d2b9bc9f41 # v1.1.22
@@ -405,7 +405,7 @@ jobs:
         uses: actions/setup-java@v5
         with:
           distribution: 'temurin'
-          java-version: 11
+          java-version: 17
 
       - name: Setup sbt launcher
         uses: sbt/setup-sbt@508b753e53cb6095967669e0911487d2b9bc9f41 # v1.1.22
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 988c383139..0a1ffbef18 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -144,7 +144,7 @@ jobs:
     strategy:
       matrix:
         os: [ubuntu-22.04]
-        java-version: [11]
+        java-version: [17]
     runs-on: ${{ matrix.os }}
     env:
       JAVA_OPTS: -Xms2048M -Xmx2048M -Xss6M -XX:ReservedCodeCacheSize=256M 
-Dfile.encoding=UTF-8
@@ -175,7 +175,7 @@ jobs:
         uses: actions/setup-java@v5
         with:
           distribution: "temurin"
-          java-version: 11
+          java-version: 17
       - name: Create Databases
         # Must run before any sbt compile step: the build's JOOQ source
         # generators connect to texera_db while compiling.
@@ -262,7 +262,7 @@ jobs:
     strategy:
       matrix:
         os: [ubuntu-22.04]
-        java-version: [11]
+        java-version: [17]
     runs-on: ${{ matrix.os }}
     env:
       JAVA_OPTS: -Xms2048M -Xmx2048M -Xss6M -XX:ReservedCodeCacheSize=256M 
-Dfile.encoding=UTF-8
@@ -293,7 +293,7 @@ jobs:
         uses: actions/setup-java@v5
         with:
           distribution: "temurin"
-          java-version: 11
+          java-version: 17
       - name: Setup Python for Scala-Python integration tests
         uses: actions/setup-python@v6
         with:
@@ -405,7 +405,7 @@ jobs:
         uses: actions/setup-java@v5
         with:
           distribution: "temurin"
-          java-version: 11
+          java-version: 17
       - name: Setup sbt launcher
         uses: sbt/setup-sbt@508b753e53cb6095967669e0911487d2b9bc9f41 # v1.1.22
       - uses: coursier/cache-action@90c37294538be80a558fd665531fcdc2b467b475 # 
v8.1.0
diff --git a/.jvmopts b/.jvmopts
new file mode 100644
index 0000000000..3f4c694a76
--- /dev/null
+++ b/.jvmopts
@@ -0,0 +1,28 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Required by Kryo: 
https://github.com/altoo-ag/pekko-kryo-serialization#using-kryo-on-jdk-17
+--add-opens=java.base/java.lang=ALL-UNNAMED
+--add-opens=java.base/java.lang.invoke=ALL-UNNAMED
+--add-opens=java.base/java.util=ALL-UNNAMED
+--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED
+--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
+
+# Required by Apache Arrow: https://arrow.apache.org/java/main/install.html
+--add-opens=java.base/java.nio=ALL-UNNAMED
+
+# Required by Apache Pekko: 
https://pekko.apache.org/docs/pekko/snapshot/release-notes/releases-2.0.html
+--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED
diff --git a/.run/ComputingUnitMaster.run.xml b/.run/ComputingUnitMaster.run.xml
index 5ffffb79e8..7d3a3aaf98 100644
--- a/.run/ComputingUnitMaster.run.xml
+++ b/.run/ComputingUnitMaster.run.xml
@@ -19,6 +19,7 @@ under the License.
 <component name="ProjectRunConfigurationManager">
   <configuration default="false" name="ComputingUnitMaster" type="Application" 
factoryName="Application">
     <option name="MAIN_CLASS_NAME" 
value="org.apache.texera.web.ComputingUnitMaster" />
+    <option name="VM_PARAMETERS" value="@$PROJECT_DIR$/.jvmopts" />
     <module name="texera.amber" />
     <shortenClasspath name="ARGS_FILE" />
     <extension name="coverage">
diff --git a/.run/ComputingUnitWorker.run.xml b/.run/ComputingUnitWorker.run.xml
index 854da67228..025e3cfd1b 100644
--- a/.run/ComputingUnitWorker.run.xml
+++ b/.run/ComputingUnitWorker.run.xml
@@ -19,6 +19,7 @@ under the License.
 <component name="ProjectRunConfigurationManager">
   <configuration default="false" name="ComputingUnitWorker" type="Application" 
factoryName="Application">
     <option name="MAIN_CLASS_NAME" 
value="org.apache.texera.web.ComputingUnitWorker" />
+    <option name="VM_PARAMETERS" value="@$PROJECT_DIR$/.jvmopts" />
     <module name="texera.amber" />
     <shortenClasspath name="ARGS_FILE" />
     <extension name="coverage">
diff --git a/AGENTS.md b/AGENTS.md
index cb1cd0fdb3..ba40082d59 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -66,7 +66,7 @@ merge.
 
 | Component | Version |
 | --- | --- |
-| Java | JDK 11 |
+| Java | JDK 17 |
 | Scala | 2.13 |
 | Python | 3.12 |
 | Node | 24 |
@@ -90,6 +90,16 @@ in [`udf.conf`](common/config/src/main/resources/udf.conf) or
 `export UDF_PYTHON_PATH="$(pwd)/../venv312/bin/python"` (env var overrides).
 Without it, `sbt` Python-integration tests fail to launch a worker.
 
+[`.jvmopts`](.jvmopts) holds every `--add-opens` flag Texera needs for
+JDK 17+, with each group annotated by its upstream source (Kryo,
+Apache Arrow, Apache Pekko). sbt's launcher and the [`.run/`](.run)
+configs read it automatically; for raw `java` launches, pass it as an
+argfile: `java @.jvmopts -jar …`. If a future library version or a new
+code path triggers an `InaccessibleObjectException`, add the open to
+`.jvmopts`. [`project/JdkOptions.scala`](project/JdkOptions.scala)
+will propagates the changed options to forked test JVMs, sbt-native-packager 
dist launchers,
+and IntelliJ.
+
 ### Branch and commit naming
 
 Short, **Conventional Commits**, same shape for branch and commit subject.
diff --git a/bin/access-control-service.dockerfile 
b/bin/access-control-service.dockerfile
index 1429171a5a..43d4c4e5a4 100644
--- a/bin/access-control-service.dockerfile
+++ b/bin/access-control-service.dockerfile
@@ -24,7 +24,7 @@
 # completeness or stability of the code, it does indicate that the project
 # has yet to be fully endorsed by the ASF.
 
-FROM sbtscala/scala-sbt:eclipse-temurin-jammy-11.0.17_8_1.9.3_2.13.11 AS build
+FROM sbtscala/scala-sbt:eclipse-temurin-jammy-17.0.5_8_1.9.3_2.13.11 AS build
 
 # Set working directory
 WORKDIR /texera
@@ -34,6 +34,7 @@ COPY common/ common/
 COPY access-control-service/ access-control-service/
 COPY project/ project/
 COPY build.sbt build.sbt
+COPY .jvmopts .jvmopts
 
 # Update system and install dependencies
 RUN apt-get update && apt-get install -y \
@@ -52,7 +53,7 @@ RUN sbt clean AccessControlService/dist
 # Unzip the texera binary
 RUN unzip access-control-service/target/universal/access-control-service-*.zip 
-d target/
 
-FROM eclipse-temurin:11-jre-jammy AS runtime
+FROM eclipse-temurin:17-jre-jammy AS runtime
 
 WORKDIR /texera
 
diff --git a/bin/computing-unit-master.dockerfile 
b/bin/computing-unit-master.dockerfile
index 5fcb54968d..191d23f2dd 100644
--- a/bin/computing-unit-master.dockerfile
+++ b/bin/computing-unit-master.dockerfile
@@ -24,7 +24,7 @@
 # completeness or stability of the code, it does indicate that the project
 # has yet to be fully endorsed by the ASF.
 
-FROM sbtscala/scala-sbt:eclipse-temurin-jammy-11.0.17_8_1.9.3_2.13.11 AS build
+FROM sbtscala/scala-sbt:eclipse-temurin-jammy-17.0.5_8_1.9.3_2.13.11 AS build
 
 # Set working directory
 WORKDIR /texera
@@ -34,6 +34,7 @@ COPY common/ common/
 COPY amber/ amber/
 COPY project/ project/
 COPY build.sbt build.sbt
+COPY .jvmopts .jvmopts
 
 # Update system and install dependencies. python3-minimal is needed by
 # bin/licensing/concat_license_binary.py below.
@@ -64,7 +65,7 @@ RUN python3 bin/licensing/concat_license_binary.py 
amber/LICENSE-binary-combined
         amber/LICENSE-binary-java \
         amber/LICENSE-binary-python
 
-FROM eclipse-temurin:11-jdk-jammy AS runtime
+FROM eclipse-temurin:17-jdk-jammy AS runtime
 
 WORKDIR /texera/amber
 
diff --git a/bin/computing-unit-worker.dockerfile 
b/bin/computing-unit-worker.dockerfile
index f600a9c05f..28d3b4cf0c 100644
--- a/bin/computing-unit-worker.dockerfile
+++ b/bin/computing-unit-worker.dockerfile
@@ -24,7 +24,7 @@
 # completeness or stability of the code, it does indicate that the project
 # has yet to be fully endorsed by the ASF.
 
-FROM sbtscala/scala-sbt:eclipse-temurin-jammy-11.0.17_8_1.9.3_2.13.11 AS build
+FROM sbtscala/scala-sbt:eclipse-temurin-jammy-17.0.5_8_1.9.3_2.13.11 AS build
 
 # Set working directory
 WORKDIR /texera
@@ -34,6 +34,7 @@ COPY common/ common/
 COPY amber/ amber/
 COPY project/ project/
 COPY build.sbt build.sbt
+COPY .jvmopts .jvmopts
 
 # Update system and install dependencies. python3-minimal is needed by
 # bin/licensing/concat_license_binary.py below.
@@ -64,7 +65,7 @@ RUN python3 bin/licensing/concat_license_binary.py 
amber/LICENSE-binary-combined
         amber/LICENSE-binary-java \
         amber/LICENSE-binary-python
 
-FROM eclipse-temurin:11-jre-jammy AS runtime
+FROM eclipse-temurin:17-jre-jammy AS runtime
 
 WORKDIR /texera/amber
 
diff --git a/bin/config-service.dockerfile b/bin/config-service.dockerfile
index 17c3d57de1..df986ee2ff 100644
--- a/bin/config-service.dockerfile
+++ b/bin/config-service.dockerfile
@@ -24,7 +24,7 @@
 # completeness or stability of the code, it does indicate that the project
 # has yet to be fully endorsed by the ASF.
 
-FROM sbtscala/scala-sbt:eclipse-temurin-jammy-11.0.17_8_1.9.3_2.13.11 AS build
+FROM sbtscala/scala-sbt:eclipse-temurin-jammy-17.0.5_8_1.9.3_2.13.11 AS build
 
 # Set working directory
 WORKDIR /texera
@@ -34,6 +34,7 @@ COPY common/ common/
 COPY config-service/ config-service/
 COPY project/ project/
 COPY build.sbt build.sbt
+COPY .jvmopts .jvmopts
 
 # Update system and install dependencies
 RUN apt-get update && apt-get install -y \
@@ -52,7 +53,7 @@ RUN sbt clean ConfigService/dist
 # Unzip the texera binary
 RUN unzip config-service/target/universal/config-service-*.zip -d target/
 
-FROM eclipse-temurin:11-jre-jammy AS runtime
+FROM eclipse-temurin:17-jre-jammy AS runtime
 
 WORKDIR /texera
 
diff --git a/bin/file-service.dockerfile b/bin/file-service.dockerfile
index 3966b5122b..1bf7032a74 100644
--- a/bin/file-service.dockerfile
+++ b/bin/file-service.dockerfile
@@ -24,7 +24,7 @@
 # completeness or stability of the code, it does indicate that the project
 # has yet to be fully endorsed by the ASF.
 
-FROM sbtscala/scala-sbt:eclipse-temurin-jammy-11.0.17_8_1.9.3_2.13.11 AS build
+FROM sbtscala/scala-sbt:eclipse-temurin-jammy-17.0.5_8_1.9.3_2.13.11 AS build
 
 # Set working directory
 WORKDIR /texera
@@ -34,6 +34,7 @@ COPY common/ common/
 COPY file-service/ file-service/
 COPY project/ project/
 COPY build.sbt build.sbt
+COPY .jvmopts .jvmopts
 
 # Update system and install dependencies
 RUN apt-get update && apt-get install -y \
@@ -52,7 +53,7 @@ RUN sbt clean FileService/dist
 # Unzip the texera binary
 RUN unzip file-service/target/universal/file-service-*.zip -d target/
 
-FROM eclipse-temurin:11-jre-jammy AS runtime
+FROM eclipse-temurin:17-jre-jammy AS runtime
 
 WORKDIR /texera
 
diff --git a/bin/texera-web-application.dockerfile 
b/bin/texera-web-application.dockerfile
index 706b0fdcfb..a829fb16aa 100644
--- a/bin/texera-web-application.dockerfile
+++ b/bin/texera-web-application.dockerfile
@@ -38,7 +38,7 @@ RUN echo "nodeLinker: node-modules" >> /frontend/.yarnrc.yml
 WORKDIR /frontend
 RUN yarn install && yarn run build
 
-FROM sbtscala/scala-sbt:eclipse-temurin-jammy-11.0.17_8_1.9.3_2.13.11 AS build
+FROM sbtscala/scala-sbt:eclipse-temurin-jammy-17.0.5_8_1.9.3_2.13.11 AS build
 
 # Set working directory
 WORKDIR /texera
@@ -48,6 +48,7 @@ COPY common/ common/
 COPY amber/ amber/
 COPY project/ project/
 COPY build.sbt build.sbt
+COPY .jvmopts .jvmopts
 
 # Update system and install dependencies. python3-minimal is needed by
 # bin/licensing/concat_license_binary.py below.
@@ -82,7 +83,7 @@ RUN python3 bin/licensing/concat_license_binary.py 
amber/LICENSE-binary-combined
         amber/LICENSE-binary-java \
         amber/LICENSE-binary-frontend
 
-FROM eclipse-temurin:11-jre-jammy AS runtime
+FROM eclipse-temurin:17-jre-jammy AS runtime
 
 WORKDIR /texera/amber
 # Copy built frontend files from the build-frontend stage to match 
FileAssetsBundle path (../../frontend/dist from /texera/amber)
diff --git a/bin/workflow-compiling-service.dockerfile 
b/bin/workflow-compiling-service.dockerfile
index b8f7f6c392..a94940ed0d 100644
--- a/bin/workflow-compiling-service.dockerfile
+++ b/bin/workflow-compiling-service.dockerfile
@@ -24,7 +24,7 @@
 # completeness or stability of the code, it does indicate that the project
 # has yet to be fully endorsed by the ASF.
 
-FROM sbtscala/scala-sbt:eclipse-temurin-jammy-11.0.17_8_1.9.3_2.13.11 AS build
+FROM sbtscala/scala-sbt:eclipse-temurin-jammy-17.0.5_8_1.9.3_2.13.11 AS build
 
 # Set working directory
 WORKDIR /texera
@@ -34,6 +34,7 @@ COPY common/ common/
 COPY workflow-compiling-service/ workflow-compiling-service/
 COPY project/ project/
 COPY build.sbt build.sbt
+COPY .jvmopts .jvmopts
 
 # Update system and install dependencies
 RUN apt-get update && apt-get install -y \
@@ -52,7 +53,7 @@ RUN sbt clean WorkflowCompilingService/dist
 # Unzip the texera binary
 RUN unzip 
workflow-compiling-service/target/universal/workflow-compiling-service-*.zip -d 
target/
 
-FROM eclipse-temurin:11-jre-jammy AS runtime
+FROM eclipse-temurin:17-jre-jammy AS runtime
 
 WORKDIR /texera
 
diff --git a/bin/workflow-computing-unit-managing-service.dockerfile 
b/bin/workflow-computing-unit-managing-service.dockerfile
index 78d0ba89db..a47e6ce06e 100644
--- a/bin/workflow-computing-unit-managing-service.dockerfile
+++ b/bin/workflow-computing-unit-managing-service.dockerfile
@@ -24,7 +24,7 @@
 # completeness or stability of the code, it does indicate that the project
 # has yet to be fully endorsed by the ASF.
 
-FROM sbtscala/scala-sbt:eclipse-temurin-jammy-11.0.17_8_1.9.3_2.13.11 AS build
+FROM sbtscala/scala-sbt:eclipse-temurin-jammy-17.0.5_8_1.9.3_2.13.11 AS build
 
 # Set working directory
 WORKDIR /texera
@@ -34,6 +34,7 @@ COPY common/ common/
 COPY computing-unit-managing-service/ computing-unit-managing-service/
 COPY project/ project/
 COPY build.sbt build.sbt
+COPY .jvmopts .jvmopts
 
 # Update system and install dependencies
 RUN apt-get update && apt-get install -y \
@@ -52,7 +53,7 @@ RUN sbt clean ComputingUnitManagingService/dist
 # Unzip the texera binary
 RUN unzip 
computing-unit-managing-service/target/universal/computing-unit-managing-service-*.zip
 -d target/
 
-FROM eclipse-temurin:11-jre-jammy AS runtime
+FROM eclipse-temurin:17-jre-jammy AS runtime
 
 WORKDIR /texera
 
diff --git a/build.sbt b/build.sbt
index e36722313e..d80a858c93 100644
--- a/build.sbt
+++ b/build.sbt
@@ -19,6 +19,11 @@ ThisBuild / organization := "org.apache.texera"
 ThisBuild / version      := "1.1.0-incubating"
 ThisBuild / scalaVersion := "2.13.18"
 
+// Pull JDK 17+ JVM flags from .jvmopts so every JVM the build launches sees 
the same list.
+import com.typesafe.sbt.packager.universal.UniversalPlugin.autoImport.Universal
+ThisBuild / Test / javaOptions ++=
+  JdkOptions.jvmFlags((ThisBuild / baseDirectory).value)
+
 // sbt-jacoco emits only HTML by default; add XML so Codecov can consume
 // per-module jacoco.xml at target/scala-2.13/jacoco/report/jacoco.xml.
 // JacocoPlugin defines a project-scoped default that overrides ThisBuild,
@@ -30,13 +35,18 @@ lazy val coverageReportSettings = Seq(
     .withFormats(JacocoReportFormats.ScalaHTML, JacocoReportFormats.XML)
 )
 
+lazy val universalJvmFlagsSettings = Seq(
+  Universal / javaOptions ++=
+    JdkOptions.jvmFlags((ThisBuild / baseDirectory).value).map("-J" + _)
+)
+
 // Per-module ASF licensing: each jar's META-INF/LICENSE describes only what 
is in that jar.
 // Modules without vendored code get Apache 2.0 only; workflow-operator 
includes mbknor attribution.
 // See project/AddMetaInfLicenseFiles.scala.
 // Dist-producing modules additionally override Universal / mappings in their 
own
 // build.sbt (not here) — see AddMetaInfLicenseFiles.distMappings.
-lazy val asfLicensingSettings = AddMetaInfLicenseFiles.defaultSettings ++ 
coverageReportSettings
-lazy val asfLicensingSettingsWithVendored = 
AddMetaInfLicenseFiles.workflowOperatorSettings ++ coverageReportSettings
+lazy val asfLicensingSettings = AddMetaInfLicenseFiles.defaultSettings ++ 
coverageReportSettings ++ universalJvmFlagsSettings
+lazy val asfLicensingSettingsWithVendored = 
AddMetaInfLicenseFiles.workflowOperatorSettings ++ coverageReportSettings ++ 
universalJvmFlagsSettings
 
 val jacksonVersion = "2.18.6"
 
diff --git a/project/JdkOptions.scala b/project/JdkOptions.scala
new file mode 100644
index 0000000000..7275e6d350
--- /dev/null
+++ b/project/JdkOptions.scala
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import sbt._
+
+import scala.io.Source
+
+/**
+ * This file reads JDK 17+ JVM flags from .jvmopts so every JVM the build
+ * launches shares one flag list.
+ *
+ * Modeled on Pekko's project/JdkOptions.scala. The JDK 8 gate is
+ * defensive: --add-opens does not exist before JDK 9, so jvmFlags
+ * stays empty there even though Texera ships JDK 17 only.
+ */
+object JdkOptions {
+
+  /** JVM flags from .jvmopts at the build root, or empty on JDK <9. */
+  def jvmFlags(baseDir: File): Seq[String] =
+    if (jdkSpecVersion < 9) Seq.empty
+    else readJvmopts(baseDir / ".jvmopts")
+
+  private def jdkSpecVersion: Int = {
+    val raw = sys.props.getOrElse("java.specification.version", "0")
+    val s = if (raw.startsWith("1.")) raw.drop(2) else raw
+    s.takeWhile(_.isDigit) match {
+      case ""    => 0
+      case digit => digit.toInt
+    }
+  }
+
+  private def readJvmopts(f: File): Seq[String] =
+    if (!f.exists()) Seq.empty
+    else {
+      val src = Source.fromFile(f)
+      try src.getLines()
+        .map(_.trim)
+        .filter(l => l.nonEmpty && !l.startsWith("#"))
+        .toList
+      finally src.close()
+    }
+}

Reply via email to