This is an automated email from the ASF dual-hosted git repository.
davidzollo pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git
The following commit(s) were added to refs/heads/dev by this push:
new 0b9e75a6ce [Improve][Core] Raise minimum Java runtime to 11 and move
CI to JDK 11/17 (#11545)
0b9e75a6ce is described below
commit 0b9e75a6ceb846cd08b06184127560cbd96c01b1
Author: Daniel <[email protected]>
AuthorDate: Fri Oct 9 01:46:33 2026 -0400
[Improve][Core] Raise minimum Java runtime to 11 and move CI to JDK 11/17
(#11545)
Co-authored-by: DanielLeens <[email protected]>
Co-authored-by: danielnadean
<[email protected]>
Co-authored-by: davidzollo <[email protected]>
Co-authored-by: davidzollo <[email protected]>
Co-authored-by: Daniel Leens <[email protected]>
Co-authored-by: Claude Sonnet 5 <[email protected]>
Co-authored-by: DanielLeens <[email protected]>
---
.github/workflows/backend.yml | 121 ++++++++++++---------
.github/workflows/benchmarks.yml | 2 +-
.github/workflows/codeql.yaml | 8 +-
.github/workflows/merge_queue.yml | 4 +-
.github/workflows/publish-docker.yaml | 8 +-
.github/workflows/upgrade_compatibility.yml | 6 +-
config/jvm_client_options | 39 +++++++
config/jvm_master_options | 38 +++++++
config/jvm_options | 38 +++++++
config/jvm_worker_options | 38 +++++++
docs/en/developer/setup.md | 3 +-
docs/en/developer/shade-guide.md | 2 +-
docs/en/edge-agent/quick-start.md | 3 +-
docs/en/engines/zeta/download-seatunnel.md | 2 +-
docs/en/engines/zeta/telemetry.md | 2 +-
docs/en/getting-started/docker/docker.md | 2 +-
docs/en/getting-started/kubernetes/kubernetes.mdx | 2 +-
docs/en/getting-started/locally/deployment.md | 4 +-
docs/en/getting-started/overview.md | 2 +-
.../introduction/concepts/incompatible-changes.md | 17 +++
docs/zh/developer/setup.md | 3 +-
docs/zh/developer/shade-guide.md | 2 +-
docs/zh/edge-agent/quick-start.md | 3 +-
docs/zh/engines/zeta/download-seatunnel.md | 2 +-
docs/zh/engines/zeta/telemetry.md | 2 +-
docs/zh/getting-started/docker/docker.md | 4 +-
docs/zh/getting-started/kubernetes/kubernetes.mdx | 2 +-
docs/zh/getting-started/locally/deployment.md | 2 +-
docs/zh/getting-started/overview.md | 2 +-
.../introduction/concepts/incompatible-changes.md | 17 +++
pom.xml | 27 ++++-
seatunnel-ci-tools/pom.xml | 3 +-
.../exception/EdgeSocketConnectorErrorCode.java | 3 +-
.../record/EdgeSocketPacketRecordDeserializer.java | 15 ++-
.../edgesocket/source/EdgeSocketSourceReader.java | 3 +-
seatunnel-connectors-v2/connector-fluss/pom.xml | 37 +++++++
seatunnel-connectors-v2/connector-iceberg/pom.xml | 6 +
.../connectors/seatunnel/kudu/util/KuduUtil.java | 31 +++++-
.../paimon/security/PaimonSecurityContext.java | 29 ++++-
.../src/main/bin/seatunnel-cluster.sh | 26 +++++
.../src/main/bin/seatunnel-connector.sh | 16 ++-
.../seatunnel-starter/src/main/bin/seatunnel.sh | 41 ++++++-
.../seatunnel/command/ServerExecuteCommand.java | 28 +----
.../command/ServerExecuteCommandTest.java | 16 +--
seatunnel-dist/src/main/docker/Dockerfile | 7 +-
.../connector/amazondynamodb/AmazondynamodbIT.java | 3 +-
.../connector-cdc-tidb-e2e/pom.xml | 1 +
.../connector-fluss-e2e/pom.xml | 3 +-
.../seatunnel/e2e/connector/python/PythonIT.java | 35 +++++-
.../src/test/resources/python_to_assert.conf | 2 +-
.../e2e/connector/rabbitmq/RabbitmqIT.java | 3 +-
.../connector-tdengine-e2e/pom.xml | 1 +
.../connector-typesense-e2e/pom.xml | 1 +
.../src/test/docker/spark/Dockerfile | 4 +-
.../flink/AbstractTestFlinkContainer.java | 4 +-
.../common/container/flink/Flink13Container.java | 8 +-
.../common/container/flink/Flink14Container.java | 6 +-
.../common/container/flink/Flink20Container.java | 7 +-
.../ConnectorPackageServiceContainer.java | 4 +-
.../container/seatunnel/SeaTunnelContainer.java | 13 ++-
.../common/container/spark/Spark2Container.java | 9 +-
.../common/container/spark/Spark3Container.java | 8 +-
.../e2e/common/util/EngineImageJdkUpgrader.java | 119 ++++++++++++++++++++
.../edge/agent/e2e/EdgeAgentContainer.java | 2 +-
.../src/test/resources/seatunnel_dockerfile | 4 +-
.../seatunnel-flink-examples/pom.xml | 1 +
.../seatunnel-flink-13-example/pom.xml | 1 +
.../seatunnel-flink-15-example/pom.xml | 1 +
.../seatunnel-flink-20-example/pom.xml | 1 +
.../seatunnel-format-protobuf/pom.xml | 1 +
tools/update_modules_check/test_ci_scope.py | 1 -
71 files changed, 744 insertions(+), 167 deletions(-)
diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml
index a55d942fb9..43f68c3656 100644
--- a/.github/workflows/backend.yml
+++ b/.github/workflows/backend.yml
@@ -36,6 +36,17 @@ env:
# GitHub-hosted runners are ephemeral, so CI does not need Ryuk to reap
containers after tests.
# Disabling it avoids transient Docker Hub pulls for testcontainers/ryuk
that can fail unrelated PRs.
TESTCONTAINERS_RYUK_DISABLED: 'true'
+ # The JDK 9+ module-opens flags Hazelcast and this project's reflective
helpers need (see
+ # config/jvm_options) no longer live here. Surefire/Failsafe-forked test
JVMs get them from the
+ # surefire.module.args property in the root pom.xml (appended to the argLine
next to
+ # surefire.jvm.args; modules that define their own argLine, such as
connector-lance, still need
+ # the unit-test step's SUREFIRE_JVM_ARGS below), which also keeps a
contributor's local
+ # `./mvnw test`/`./mvnw verify` on JDK 11/17 in parity with CI. The packaged
launcher scripts
+ # (seatunnel.sh, seatunnel-cluster.sh) inject the same flags themselves for
the e2e Docker
+ # containers this workflow spins up, independent of this workflow's own
environment. Setting
+ # JAVA_TOOL_OPTIONS here applied the flags to every process every job
happened to run, including
+ # non-test jobs and non-JVM tools, and printed a "Picked up
JAVA_TOOL_OPTIONS" line from every
+ # child process; scoping it to the two places that actually need it removes
both problems.
jobs:
license-header:
@@ -486,7 +497,7 @@ jobs:
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
- java-version: '8'
+ java-version: '17'
cache: 'maven'
- name: Install
uses: nick-fields/retry@v3
@@ -571,7 +582,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest', 'windows-latest' ]
# The all-modules unit test build now takes 70-88 minutes on ubuntu-latest
and keeps growing
# with every new connector; a 90 minute budget left so little headroom
that ordinary runner
@@ -589,13 +600,24 @@ jobs:
run: ./mvnw -B -T 1 clean verify -DskipUT=false -DskipIT=true
-D"license.skipAddThirdParty"=true -D"skip.ui"=true
"-Dsurefire.jvm.args=$SUREFIRE_JVM_ARGS" --no-snapshot-updates
env:
MAVEN_OPTS: -Xmx1536m -Dfile.encoding=UTF-8
- SUREFIRE_JVM_ARGS: -Xmx3072m -XX:MaxMetaspaceSize=512m
-Dfile.encoding=UTF-8
+ # This CLI -Dsurefire.jvm.args replaces surefire.jvm.args in every
module. The JDK 9+
+ # --add-opens/--add-exports flags (needed by JDK 17 unit tests, JEP
396) are repeated
+ # here on purpose: the root pom carries them in
surefire.module.args, but a module that
+ # defines its own surefire <argLine> bypasses the root argLine and
only sees
+ # surefire.jvm.args. connector-lance does exactly that (Arrow needs
+ # --add-opens=java.base/java.nio on JDK 17), and its unit tests
failed with
+ # InaccessibleObjectException when these flags were removed from
this step.
+ # Keep this list in sync with surefire.module.args in the root
pom.xml. The duplication
+ # is tracked in apache/seatunnel#12655; do not remove these flags
before that is fixed.
+ SUREFIRE_JVM_ARGS: -Xmx3072m -XX:MaxMetaspaceSize=512m
-Dfile.encoding=UTF-8 --add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.net=ALL-UNNAMED
--add-opens=java.base/java.nio=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED
if: runner.os != 'Windows'
- name: run all modules unit test (Windows)
run: ./mvnw -B -T 1 clean verify -DskipUT=false -DskipIT=true
-D"license.skipAddThirdParty"=true -D"skip.ui"=true
"-Dsurefire.jvm.args=$env:SUREFIRE_JVM_ARGS" --no-snapshot-updates
env:
MAVEN_OPTS: -Xmx1536m -Dfile.encoding=UTF-8
- SUREFIRE_JVM_ARGS: -Xmx3072m -XX:MaxMetaspaceSize=512m
-Dfile.encoding=UTF-8
+ # Keep in sync with the non-Windows step above; see its comment for
why the module
+ # flags must be repeated here as well as in the pom.xml
surefire.module.args property.
+ SUREFIRE_JVM_ARGS: -Xmx3072m -XX:MaxMetaspaceSize=512m
-Dfile.encoding=UTF-8 --add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.net=ALL-UNNAMED
--add-opens=java.base/java.nio=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED
if: runner.os == 'Windows'
- name: Upload test reports
if: failure()
@@ -611,7 +633,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
steps:
- uses: actions/checkout@v4
@@ -661,7 +683,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 180
steps:
@@ -699,7 +721,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 180
steps:
@@ -737,7 +759,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 300
steps:
@@ -775,7 +797,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 200
steps:
@@ -812,7 +834,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 180
steps:
@@ -849,7 +871,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 210
steps:
@@ -886,7 +908,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 210
steps:
@@ -924,7 +946,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 210
steps:
@@ -962,7 +984,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 150
steps:
@@ -993,7 +1015,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -1024,7 +1046,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 45
steps:
@@ -1067,7 +1089,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
# Part-1 alone takes 99-107 minutes on ubuntu-latest; the UDF E2E module
adds its own build and tests.
timeout-minutes: 135
@@ -1102,7 +1124,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
# A green run of this job takes about 149 minutes on ubuntu-latest, so the
previous 150
# minute budget cancelled runs that were already on their last test class.
@@ -1140,7 +1162,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 150
steps:
@@ -1177,7 +1199,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 150
steps:
@@ -1214,7 +1236,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 150
steps:
@@ -1251,7 +1273,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 150
steps:
@@ -1288,7 +1310,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 150
steps:
@@ -1325,7 +1347,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 150
steps:
@@ -1362,7 +1384,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 150
steps:
@@ -1399,7 +1421,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 150
steps:
@@ -1433,7 +1455,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 150
steps:
@@ -1467,7 +1489,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
# A green run of this job takes 113-115 minutes on ubuntu-latest
(JdbcOracleIT alone is
# about 25 minutes), so the previous 120 minute budget left ordinary
runner variance no
@@ -1504,7 +1526,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -1538,7 +1560,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -1572,7 +1594,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -1606,7 +1628,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -1640,7 +1662,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -1674,7 +1696,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -1708,7 +1730,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 180
steps:
@@ -1739,7 +1761,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
# Kudu E2E expands each @TestTemplate case across several PR test
containers.
timeout-minutes: 90
@@ -1771,7 +1793,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -1800,8 +1822,9 @@ jobs:
if: needs.changes.outputs.api == 'true' || needs.changes.outputs.engine ==
'true' || contains(fromJSON(needs.changes.outputs.it-modules),
'connector-google-pubsub-e2e')
runs-on: ${{ matrix.os }}
strategy:
+ fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -1832,7 +1855,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 210
steps:
@@ -1863,7 +1886,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -1894,7 +1917,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 180
steps:
@@ -1925,7 +1948,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -1956,7 +1979,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 180
steps:
@@ -1987,7 +2010,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 180
steps:
@@ -2018,7 +2041,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 210
steps:
@@ -2054,7 +2077,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -2085,7 +2108,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 120
steps:
@@ -2116,7 +2139,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 210
steps:
@@ -2147,7 +2170,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [ '8', '11' ]
+ java: [ '11', '17' ]
os: [ 'ubuntu-latest' ]
timeout-minutes: 180
steps:
diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml
index 3d31440bd8..4a9d0e3b2e 100644
--- a/.github/workflows/benchmarks.yml
+++ b/.github/workflows/benchmarks.yml
@@ -71,7 +71,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java-version: [ '8', '11' ]
+ java-version: [ '11', '17' ]
env:
BENCHMARK_SUITE: ${{ github.event_name == 'schedule' &&
'benchmarks_core' || '' }}
diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml
index 677e7f52c0..224311b485 100644
--- a/.github/workflows/codeql.yaml
+++ b/.github/workflows/codeql.yaml
@@ -37,11 +37,11 @@ jobs:
uses: actions/checkout@v2
with:
submodules: true
- - name: Set up JDK 1.8
- uses: actions/setup-java@v2
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
with:
- java-version: 8
- distribution: 'adopt'
+ java-version: '17'
+ distribution: 'temurin'
- name: Cache local Maven repository
uses: actions/cache@v4
with:
diff --git a/.github/workflows/merge_queue.yml
b/.github/workflows/merge_queue.yml
index 35b67320bb..6b1c29cf77 100644
--- a/.github/workflows/merge_queue.yml
+++ b/.github/workflows/merge_queue.yml
@@ -36,11 +36,11 @@ jobs:
steps:
- name: Checkout merge group
uses: actions/checkout@v4
- - name: Set up JDK 8
+ - name: Set up JDK 11
uses: actions/setup-java@v4
with:
distribution: temurin
- java-version: '8'
+ java-version: '11'
cache: maven
# Compile the standard modules with the CI profile.
- name: Compile main and test sources
diff --git a/.github/workflows/publish-docker.yaml
b/.github/workflows/publish-docker.yaml
index 98f08f5778..68f4cad308 100644
--- a/.github/workflows/publish-docker.yaml
+++ b/.github/workflows/publish-docker.yaml
@@ -51,11 +51,11 @@ jobs:
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- - name: Set up JDK 1.8
- uses: actions/setup-java@v2
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
with:
- java-version: 8
- distribution: 'adopt'
+ java-version: '17'
+ distribution: 'temurin'
- name: Log in to the Container registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f #
v4.6.0
diff --git a/.github/workflows/upgrade_compatibility.yml
b/.github/workflows/upgrade_compatibility.yml
index 1c3819c08c..367ad3bc4b 100644
--- a/.github/workflows/upgrade_compatibility.yml
+++ b/.github/workflows/upgrade_compatibility.yml
@@ -52,7 +52,11 @@ jobs:
- uses: actions/setup-java@v4
with:
distribution: temurin
- java-version: "8"
+ # JDK 11, not 17: this job boots the OLD release (2.3.13), whose
bundled
+ # config/jvm_*_options predate the JDK 9+ --add-opens flags, so
running it under
+ # JDK 17's strong encapsulation could fail for reasons unrelated to
upgrade
+ # compatibility. Java 11 is the minimum runtime both versions
support.
+ java-version: "11"
- name: Test upgrade compatibility tooling
run: bash tools/upgrade_compatibility/run_upgrade_compatibility_test.sh
diff --git a/config/jvm_client_options b/config/jvm_client_options
index 462e1374c1..aca28cdef5 100644
--- a/config/jvm_client_options
+++ b/config/jvm_client_options
@@ -15,6 +15,45 @@
# limitations under the License.
#
+# JDK 9+ module system compatibility. Two independent consumers need these
flags:
+# 1. The Hazelcast client this process embeds to talk to the Zeta engine.
Its own
+# serialization and networking internals reflectively touch these JDK
APIs; nothing in
+# this codebase calls them directly, so there is no first-party call site
in our source
+# to point to for these.
+# 2. This project's own reflective Kerberos configuration reload helpers
(KuduUtil,
+# PaimonSecurityContext) and the connector classloader injection helpers
+# (AbstractPluginDiscovery, ConfigValidationUtils, the Flink starter
plugin loaders),
+# which are named per-flag below.
+# Source of truth: the launcher scripts (seatunnel.sh, seatunnel-cluster.sh)
append the mandatory
+# flags below themselves, skipping any already present. The entries in this
file are a
+# convenience and documentation; do not remove the launcher injection assuming
this file is
+# sufficient, because a preserved config directory would then silently lose
the flags.
+# Without these flags the Kerberos reload helpers log an ERROR naming the
missing flag; other
+# consumers may not report it until the affected path is actually exercised.
+# Evidence status: only java.net has a captured failing stack trace
(ReflectionUtilsTest).
+# The other entries are not proven necessary by a captured failure on this
project's CI and
+# are candidates to trim later.
+# Required by Hazelcast client internals (see note 1 above).
+# Evidence: no captured failure on this project's CI; candidate to trim.
+--add-opens=java.base/java.lang=ALL-UNNAMED
+# Required by URLClassLoader#addURL reflection: AbstractPluginDiscovery,
+# ConfigValidationUtils, and the Flink starter plugin loaders inject connector
jars this way.
+--add-opens=java.base/java.net=ALL-UNNAMED
+# Required by Hazelcast client internals (see note 1 above).
+# Evidence: also required by Apache Arrow (connector-lance unit tests fail on
JDK 17 without it).
+--add-opens=java.base/java.nio=ALL-UNNAMED
+# Required by Hazelcast client internals (see note 1 above).
+# Evidence: no captured failure on this project's CI; candidate to trim.
+--add-opens=java.base/java.util=ALL-UNNAMED
+# Required by Hazelcast client internals (see note 1 above).
+# Evidence: no captured failure on this project's CI; candidate to trim.
+--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
+# Required by the Kerberos configuration reload helpers KuduUtil and
PaimonSecurityContext,
+# which reflectively call sun.security.krb5.Config#refresh() to pick
+# up a custom krb5.conf without a JVM restart.
+# Evidence: no captured failure on this project's CI; kept for the reflective
reload.
+--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED
+
# JVM Heap
-Xms256m
-Xmx512m
diff --git a/config/jvm_master_options b/config/jvm_master_options
index d435a7d275..cebd38e4b1 100644
--- a/config/jvm_master_options
+++ b/config/jvm_master_options
@@ -15,6 +15,44 @@
# limitations under the License.
#
+# JDK 9+ module system compatibility. Two independent consumers need these
flags:
+# 1. Hazelcast, which the Zeta engine is built on. Its own serialization and
networking
+# internals reflectively touch these JDK APIs; nothing in this codebase
calls them
+# directly, so there is no first-party call site in our source to point
to for these.
+# 2. This project's own reflective code: the Kerberos configuration reload
helpers
+# (KuduUtil, PaimonSecurityContext) and the connector classloader
injection helpers
+# (AbstractPluginDiscovery, ConfigValidationUtils, the Flink starter
plugin loaders),
+# which are named per-flag below.
+# Source of truth: the launcher scripts (seatunnel.sh, seatunnel-cluster.sh)
append the mandatory
+# flags below themselves, skipping any already present. The entries in this
file are a
+# convenience and documentation; do not remove the launcher injection assuming
this file is
+# sufficient, because a preserved config directory would then silently lose
the flags.
+# Without these flags the Kerberos reload helpers log an ERROR naming the
missing flag; other
+# consumers may not report it until the affected path is actually exercised.
+# Evidence status: only java.net has a captured failing stack trace
(ReflectionUtilsTest).
+# The other entries are not proven necessary by a captured failure on this
project's CI and
+# are candidates to trim later.
+# Required by Hazelcast internals (see note 1 above).
+# Evidence: no captured failure on this project's CI; candidate to trim.
+--add-opens=java.base/java.lang=ALL-UNNAMED
+# Required by URLClassLoader#addURL reflection: AbstractPluginDiscovery,
+# ConfigValidationUtils, and the Flink starter plugin loaders inject connector
jars this way.
+--add-opens=java.base/java.net=ALL-UNNAMED
+# Required by Hazelcast internals (see note 1 above).
+# Evidence: also required by Apache Arrow (connector-lance unit tests fail on
JDK 17 without it).
+--add-opens=java.base/java.nio=ALL-UNNAMED
+# Required by Hazelcast internals (see note 1 above).
+# Evidence: no captured failure on this project's CI; candidate to trim.
+--add-opens=java.base/java.util=ALL-UNNAMED
+# Required by Hazelcast internals (see note 1 above).
+# Evidence: no captured failure on this project's CI; candidate to trim.
+--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
+# Required by the Kerberos configuration reload helpers KuduUtil and
PaimonSecurityContext,
+# which reflectively call sun.security.krb5.Config#refresh() to pick
+# up a custom krb5.conf without a JVM restart.
+# Evidence: no captured failure on this project's CI; kept for the reflective
reload.
+--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED
+
# JVM Heap
# -Xms2g
# -Xmx2g
diff --git a/config/jvm_options b/config/jvm_options
index 0e5d289ea0..34c44ad4b0 100644
--- a/config/jvm_options
+++ b/config/jvm_options
@@ -15,6 +15,44 @@
# limitations under the License.
#
+# JDK 9+ module system compatibility. Two independent consumers need these
flags:
+# 1. Hazelcast, which the Zeta engine is built on. Its own serialization and
networking
+# internals reflectively touch these JDK APIs; nothing in this codebase
calls them
+# directly, so there is no first-party call site in our source to point
to for these.
+# 2. This project's own reflective code: the Kerberos configuration reload
helpers
+# (KuduUtil, PaimonSecurityContext) and the connector classloader
injection helpers
+# (AbstractPluginDiscovery, ConfigValidationUtils, the Flink starter
plugin loaders),
+# which are named per-flag below.
+# Source of truth: the launcher scripts (seatunnel.sh, seatunnel-cluster.sh)
append the mandatory
+# flags below themselves, skipping any already present. The entries in this
file are a
+# convenience and documentation; do not remove the launcher injection assuming
this file is
+# sufficient, because a preserved config directory would then silently lose
the flags.
+# Without these flags the Kerberos reload helpers log an ERROR naming the
missing flag; other
+# consumers may not report it until the affected path is actually exercised.
+# Evidence status: only java.net has a captured failing stack trace
(ReflectionUtilsTest).
+# The other entries are not proven necessary by a captured failure on this
project's CI and
+# are candidates to trim later.
+# Required by Hazelcast internals (see note 1 above).
+# Evidence: no captured failure on this project's CI; candidate to trim.
+--add-opens=java.base/java.lang=ALL-UNNAMED
+# Required by URLClassLoader#addURL reflection: AbstractPluginDiscovery,
+# ConfigValidationUtils, and the Flink starter plugin loaders inject connector
jars this way.
+--add-opens=java.base/java.net=ALL-UNNAMED
+# Required by Hazelcast internals (see note 1 above).
+# Evidence: also required by Apache Arrow (connector-lance unit tests fail on
JDK 17 without it).
+--add-opens=java.base/java.nio=ALL-UNNAMED
+# Required by Hazelcast internals (see note 1 above).
+# Evidence: no captured failure on this project's CI; candidate to trim.
+--add-opens=java.base/java.util=ALL-UNNAMED
+# Required by Hazelcast internals (see note 1 above).
+# Evidence: no captured failure on this project's CI; candidate to trim.
+--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
+# Required by the Kerberos configuration reload helpers KuduUtil and
PaimonSecurityContext,
+# which reflectively call sun.security.krb5.Config#refresh() to pick
+# up a custom krb5.conf without a JVM restart.
+# Evidence: no captured failure on this project's CI; kept for the reflective
reload.
+--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED
+
# JVM Heap
# -Xms2g
# -Xmx2g
diff --git a/config/jvm_worker_options b/config/jvm_worker_options
index d435a7d275..cebd38e4b1 100644
--- a/config/jvm_worker_options
+++ b/config/jvm_worker_options
@@ -15,6 +15,44 @@
# limitations under the License.
#
+# JDK 9+ module system compatibility. Two independent consumers need these
flags:
+# 1. Hazelcast, which the Zeta engine is built on. Its own serialization and
networking
+# internals reflectively touch these JDK APIs; nothing in this codebase
calls them
+# directly, so there is no first-party call site in our source to point
to for these.
+# 2. This project's own reflective code: the Kerberos configuration reload
helpers
+# (KuduUtil, PaimonSecurityContext) and the connector classloader
injection helpers
+# (AbstractPluginDiscovery, ConfigValidationUtils, the Flink starter
plugin loaders),
+# which are named per-flag below.
+# Source of truth: the launcher scripts (seatunnel.sh, seatunnel-cluster.sh)
append the mandatory
+# flags below themselves, skipping any already present. The entries in this
file are a
+# convenience and documentation; do not remove the launcher injection assuming
this file is
+# sufficient, because a preserved config directory would then silently lose
the flags.
+# Without these flags the Kerberos reload helpers log an ERROR naming the
missing flag; other
+# consumers may not report it until the affected path is actually exercised.
+# Evidence status: only java.net has a captured failing stack trace
(ReflectionUtilsTest).
+# The other entries are not proven necessary by a captured failure on this
project's CI and
+# are candidates to trim later.
+# Required by Hazelcast internals (see note 1 above).
+# Evidence: no captured failure on this project's CI; candidate to trim.
+--add-opens=java.base/java.lang=ALL-UNNAMED
+# Required by URLClassLoader#addURL reflection: AbstractPluginDiscovery,
+# ConfigValidationUtils, and the Flink starter plugin loaders inject connector
jars this way.
+--add-opens=java.base/java.net=ALL-UNNAMED
+# Required by Hazelcast internals (see note 1 above).
+# Evidence: also required by Apache Arrow (connector-lance unit tests fail on
JDK 17 without it).
+--add-opens=java.base/java.nio=ALL-UNNAMED
+# Required by Hazelcast internals (see note 1 above).
+# Evidence: no captured failure on this project's CI; candidate to trim.
+--add-opens=java.base/java.util=ALL-UNNAMED
+# Required by Hazelcast internals (see note 1 above).
+# Evidence: no captured failure on this project's CI; candidate to trim.
+--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
+# Required by the Kerberos configuration reload helpers KuduUtil and
PaimonSecurityContext,
+# which reflectively call sun.security.krb5.Config#refresh() to pick
+# up a custom krb5.conf without a JVM restart.
+# Evidence: no captured failure on this project's CI; kept for the reflective
reload.
+--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED
+
# JVM Heap
# -Xms2g
# -Xmx2g
diff --git a/docs/en/developer/setup.md b/docs/en/developer/setup.md
index 720f06d987..e808f4503d 100644
--- a/docs/en/developer/setup.md
+++ b/docs/en/developer/setup.md
@@ -16,7 +16,7 @@ Before we start talking about how to set up the environment,
we need to do some
have installed the following software:
* [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
installed.
-* [Java](https://www.java.com/en/download/) ( JDK8/JDK11 are supported by now)
installed and `JAVA_HOME` set.
+* [Java](https://www.java.com/en/download/) (JDK11/JDK17 are supported by now)
installed and `JAVA_HOME` set.
* [Scala](https://www.scala-lang.org/download/2.11.12.html) (only scala
2.11.12 supported by now) installed.
* [JetBrains IDEA](https://www.jetbrains.com/idea/) installed.
@@ -128,4 +128,3 @@ sink {
Console {}
}
```
-
diff --git a/docs/en/developer/shade-guide.md b/docs/en/developer/shade-guide.md
index a7853ffee2..c78a1c0a65 100644
--- a/docs/en/developer/shade-guide.md
+++ b/docs/en/developer/shade-guide.md
@@ -85,7 +85,7 @@ Child modules declare dependencies **without** a `<version>`
element — the ver
### Prerequisites
-- Java 8+
+- Java 11+
- Maven 3.x
### Clone and Build
diff --git a/docs/en/edge-agent/quick-start.md
b/docs/en/edge-agent/quick-start.md
index 5379ac2e7a..0d0b895b43 100644
--- a/docs/en/edge-agent/quick-start.md
+++ b/docs/en/edge-agent/quick-start.md
@@ -31,7 +31,7 @@ The install root contains bin/, config/, and starter/.
### Prerequisites
-- Java 8 or 11 on the edge host, with JAVA_HOME set.
+- Java 11 or 17 on the edge host, with JAVA_HOME set.
- No SeaTunnel Engine and no EdgeSocket connectivity required.
- Writable install root (default WAL data/wal.db, logs, edge-agent.id).
@@ -182,4 +182,3 @@ Keep edge-agent.id and the data/ directory (default wal.db
plus -wal/-shm) when
Once you have completed the quick start, continue with the [Deployment
Guide](deployment-guide.md) for production setup, or see the [Configuration
Reference](configuration.md) for full parameters. For a complete documentation
map, visit [About Edge Agent](about.md#recommended-reading-order).
-
diff --git a/docs/en/engines/zeta/download-seatunnel.md
b/docs/en/engines/zeta/download-seatunnel.md
index 505aac6d61..7c40421f29 100644
--- a/docs/en/engines/zeta/download-seatunnel.md
+++ b/docs/en/engines/zeta/download-seatunnel.md
@@ -11,7 +11,7 @@ import TabItem from '@theme/TabItem';
Before starting to download SeaTunnel, you need to ensure that you have
installed the following software required by SeaTunnel:
-* Install [Java](https://www.java.com/en/download/) (Java 8 or 11, and other
versions higher than Java 8 can theoretically work) and set `JAVA_HOME`.
+* Install [Java](https://www.java.com/en/download/) (Java 11 or Java 17) and
set `JAVA_HOME`.
## Step 2: Download SeaTunnel
diff --git a/docs/en/engines/zeta/telemetry.md
b/docs/en/engines/zeta/telemetry.md
index 71ac33a907..1d81aed91a 100644
--- a/docs/en/engines/zeta/telemetry.md
+++ b/docs/en/engines/zeta/telemetry.md
@@ -215,7 +215,7 @@ This metric is exported by the active master only. It
reports only an aggregate
| jvm_memory_pool_allocated_bytes_total | Counter | **pool**,including:
"Code Cache" "PS Eden Space" "PS Old Ge" "PS Survivor Space" "Compressed Class
Space" "Metaspace" | Total bytes allocated in a
given JVM memory pool. Only updated after GC, not continuously |
| jvm_gc_collection_seconds_count | Summary | **gc**,including: "PS
Scavenge" "PS MarkSweep"
| Time spent in a given JVM
garbage collector in seconds |
| jvm_gc_collection_seconds_sum | Summary | **gc**,including: "PS
Scavenge" "PS MarkSweep"
| Time spent in a given JVM
garbage collector in seconds |
-| jvm_info | Gauge | **runtime**, for
example: "Java(TM) SE Runtime Environment". **vendor**, for example: "Oracle
Corporation". **version** ,for example: "1.8.0_212-b10" | VM version info
|
+| jvm_info | Gauge | **runtime**, for
example: "Java(TM) SE Runtime Environment". **vendor**, for example: "Oracle
Corporation". **version** ,for example: "11.0.22+7" | VM version info
|
| process_cpu_seconds_total | Counter | -
| Total user and system CPU
time spent in seconds |
| process_start_time_seconds | Gauge | -
| Start time of the process
since unix epoch in seconds |
| process_open_fds | Gauge | -
| Number of open file
descriptors
|
diff --git a/docs/en/getting-started/docker/docker.md
b/docs/en/getting-started/docker/docker.md
index 9a91f9f835..5e3ac840d6 100644
--- a/docs/en/getting-started/docker/docker.md
+++ b/docs/en/getting-started/docker/docker.md
@@ -64,7 +64,7 @@ docker images | grep apache/seatunnel
The Dockerfile is like this:
```dockerfile
-FROM seatunnelhub/openjdk:8u342
+FROM eclipse-temurin:11-jdk
ARG VERSION
# Build from Source Code And Copy it into image
diff --git a/docs/en/getting-started/kubernetes/kubernetes.mdx
b/docs/en/getting-started/kubernetes/kubernetes.mdx
index 896f7a44bb..5431ec45b4 100644
--- a/docs/en/getting-started/kubernetes/kubernetes.mdx
+++ b/docs/en/getting-started/kubernetes/kubernetes.mdx
@@ -89,7 +89,7 @@ minikube start --kubernetes-version=v1.23.3
For production environments, pin the SeaTunnel image tag and build commonly
used connectors, dependencies, and base configuration into the image. This
avoids uncertainty caused by downloading dependencies at runtime.
```Dockerfile
-FROM seatunnelhub/openjdk:8u342
+FROM eclipse-temurin:11-jdk
ARG SEATUNNEL_VERSION
ENV SEATUNNEL_HOME="/opt/seatunnel"
diff --git a/docs/en/getting-started/locally/deployment.md
b/docs/en/getting-started/locally/deployment.md
index d640d4023b..077faded16 100644
--- a/docs/en/getting-started/locally/deployment.md
+++ b/docs/en/getting-started/locally/deployment.md
@@ -11,7 +11,7 @@ import TabItem from '@theme/TabItem';
Before starting to download SeaTunnel, you need to ensure that you have
installed the following software required by SeaTunnel:
-* Install [Java](https://www.java.com/en/download/) (Java 8 or 11, and other
versions higher than Java 8 can theoretically work) and set `JAVA_HOME`.
+* Install [Java](https://www.java.com/en/download/) (Java 11 or Java 17) and
set `JAVA_HOME`.
## Download SeaTunnel Release Package
@@ -92,9 +92,7 @@ If you want to install connector plugins by manually
downloading connectors, you
:::
:::note Developer note
-
This local deployment guide assumes that you use an official binary release
package. If you need to validate unreleased code, debug SeaTunnel source code,
or prepare a custom distribution, see [Set Up Develop
Environment](../../developer/setup.md).
-
:::
# Run SeaTunnel
diff --git a/docs/en/getting-started/overview.md
b/docs/en/getting-started/overview.md
index ceced1703b..d49561aac0 100644
--- a/docs/en/getting-started/overview.md
+++ b/docs/en/getting-started/overview.md
@@ -60,7 +60,7 @@ If you want to validate your installation in the shortest
path:
## What You Need Before Using SeaTunnel
-- Java 8 or Java 11 with `JAVA_HOME` configured
+- Java 11 or Java 17 with `JAVA_HOME` configured
- A SeaTunnel binary package from the [download
page](https://seatunnel.apache.org/download)
- Required connector plugins installed under `${SEATUNNEL_HOME}/connectors/`
- Any third-party driver jars required by your chosen connectors
diff --git a/docs/en/introduction/concepts/incompatible-changes.md
b/docs/en/introduction/concepts/incompatible-changes.md
index b89ac06de8..ac37c957a3 100644
--- a/docs/en/introduction/concepts/incompatible-changes.md
+++ b/docs/en/introduction/concepts/incompatible-changes.md
@@ -5,6 +5,23 @@ You need to check this document before you upgrade to related
version.
## dev
+### Runtime Requirements
+
+- **Breaking Change: Minimum Java runtime raised from Java 8 to Java 11**
+ - **Affected component**: every module — the whole distribution, the Zeta
engine, all connectors, and the published Docker image
+ - **Description**: The build now targets Java 11 (`maven.compiler.source`
and `maven.compiler.target` are `11`), so every published jar contains class
file version 55. GitHub CI compiles and tests on JDK 17 against this Java 11
baseline, and the published Docker image moved from
`seatunnelhub/openjdk:8u342` to `eclipse-temurin:11-jdk`, keeping a full JDK
rather than a JRE so `jps`/`jstack`/`jmap` stay available for diagnosing a
running node.
+ - **Impact**:
+ - A Java 8 JVM can no longer load SeaTunnel classes. Startup fails with
`java.lang.UnsupportedClassVersionError: ... has been compiled by a more recent
version of the Java Runtime (class file version 55.0)`. This applies to the
client, to the Zeta master and worker nodes, and to any process that loads
connector jars.
+ - **Flink**: the JobManager and TaskManager JVMs load SeaTunnel connector
classes, so the whole Flink cluster must run Java 11 or later, not just the
submitting client. Flink supports Java 11 from 1.13 onward, and the official
Flink images publish `-java11` tags.
+ - **Spark**: the driver and executor JVMs load SeaTunnel connector
classes, so the whole Spark cluster must run Java 11 or later. Spark only
gained official Java 11 support in Spark 3.0 (SPARK-24417). Spark 2.4 does
still start under Java 11, but it logs illegal reflective access warnings and
puts an old commons-lang3 on the classpath that some connectors trip over, so
Spark 3.x is strongly recommended.
+ - Third-party connectors that are themselves compiled for Java 8 keep
working. A Java 11 JVM loads older class files without changes, so only the JVM
version matters, not the bytecode level of your own jars.
+ - **Migration Guide**:
+ 1. Upgrade the JVM to Java 11 or Java 17 on every node that runs SeaTunnel
code: the client, the Zeta master and workers, and the Flink or Spark cluster
you submit to.
+ 2. If you submit to Flink, move the cluster onto an image or deployment
that runs Java 11 or later.
+ 3. If you submit to Spark 2.4, upgrade to Spark 3.x running on Java 11 or
later. There is no Spark 2.x release that supports Java 11.
+ 4. If you customized `${SEATUNNEL_HOME}/config/jvm_options` (or the
client, master and worker variants), check your additions for flags that Java
11 removed, such as `-XX:+UseConcMarkSweepGC` or `-XX:MaxPermSize`, because the
JVM refuses to start on an unrecognized flag. The options shipped by default
are already Java 11 compatible.
+ 5. You do not have to copy the new JDK module flags into a preserved
config directory. `seatunnel.sh` and `seatunnel-cluster.sh` append the
mandatory `--add-opens`/`--add-exports` flags (`java.base/java.lang`,
`java.net`, `java.nio`, `java.util`, `sun.nio.ch`, and
`java.security.jgss/sun.security.krb5`) themselves and skip any your
`jvm_*_options` already carries, so an in-place upgrade that keeps an old
`config/` directory (a mounted Docker volume or a Kubernetes ConfigMap) still
st [...]
+
### SQL TINYINT array schema
The Zeta SQL ARRAY function now declares TINYINT elements as `ARRAY<TINYINT>`,
matching the Byte values it emits. The previous `ARRAY<STRING>` declaration
could fail in schema-dependent row consumers. Update downstream declarations
that assumed STRING elements; cast the SQL values to STRING explicitly when
that schema is required. Restart affected jobs with the corrected schema rather
than restoring state that relies on the old declaration.
diff --git a/docs/zh/developer/setup.md b/docs/zh/developer/setup.md
index 8e9594dfc1..dbcaec1482 100644
--- a/docs/zh/developer/setup.md
+++ b/docs/zh/developer/setup.md
@@ -14,7 +14,7 @@
在设置开发环境之前, 需要做一些准备工作, 确保你安装了以下软件:
* 安装 [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)。
-* 安装 [Java](https://www.java.com/en/download/) (目前只支持 JDK8/JDK11) 并且设置
`JAVA_HOME` 环境变量。
+* 安装 [Java](https://www.java.com/en/download/) (目前只支持 JDK11/JDK17) 并且设置
`JAVA_HOME` 环境变量。
* 安装 [Scala](https://www.scala-lang.org/download/2.11.12.html) (目前只支持 scala
2.11.12)。
* 安装 [JetBrains IDEA](https://www.jetbrains.com/idea/)。
@@ -122,4 +122,3 @@ sink {
Console {}
}
```
-
diff --git a/docs/zh/developer/shade-guide.md b/docs/zh/developer/shade-guide.md
index 9aca196d7c..98da196b06 100644
--- a/docs/zh/developer/shade-guide.md
+++ b/docs/zh/developer/shade-guide.md
@@ -85,7 +85,7 @@ ${library.version}-${seatunnel.shade.version}
### 前置条件
-- Java 8+
+- Java 11+
- Maven 3.x
### 克隆并构建
diff --git a/docs/zh/edge-agent/quick-start.md
b/docs/zh/edge-agent/quick-start.md
index dbf727535c..b4355e2e0e 100644
--- a/docs/zh/edge-agent/quick-start.md
+++ b/docs/zh/edge-agent/quick-start.md
@@ -31,7 +31,7 @@ cd "$EDGE_AGENT_HOME"
### 前提
-- 边缘主机已安装 Java 8 或 11,并设置 JAVA_HOME。
+- 边缘主机已安装 Java 11 或 17,并设置 JAVA_HOME。
- 不需要 SeaTunnel Engine,也不需要 EdgeSocket 网络连通。
- 安装根目录可写(默认持久化文件 data、日志、edge-agent.id)。
@@ -182,4 +182,3 @@ sh bin/seatunnel-edge-agent.sh stop
快速开始完成后,建议继续阅读 [部署指南](deployment-guide.md) 进行生产部署,或查看
[配置参数说明](configuration.md) 了解完整参数。全部文档导航见 [关于 Edge Agent](about.md#推荐阅读顺序)。
-
diff --git a/docs/zh/engines/zeta/download-seatunnel.md
b/docs/zh/engines/zeta/download-seatunnel.md
index 7f2f8aca54..63dee017d2 100644
--- a/docs/zh/engines/zeta/download-seatunnel.md
+++ b/docs/zh/engines/zeta/download-seatunnel.md
@@ -11,7 +11,7 @@ import TabItem from '@theme/TabItem';
在开始下载SeaTunnel之前,您需要确保您已经安装了SeaTunnel所需要的以下软件:
-* 安装[Java](https://www.java.com/en/download/) (Java 8 或 11, 其他高于Java
8的版本理论上也可以工作) 以及设置 `JAVA_HOME`。
+* 安装[Java](https://www.java.com/en/download/) (Java 11 或 Java 17) 以及设置
`JAVA_HOME`。
## 步骤 2: 下载 SeaTunnel
diff --git a/docs/zh/engines/zeta/telemetry.md
b/docs/zh/engines/zeta/telemetry.md
index bd9841c424..4e2bd1d14e 100644
--- a/docs/zh/engines/zeta/telemetry.md
+++ b/docs/zh/engines/zeta/telemetry.md
@@ -207,7 +207,7 @@ worker 发送 `RequestSlotOperation` 请求以预留 slot。这些指标用于
| jvm_memory_pool_allocated_bytes_total | Counter | **pool**,包括:"Code
Cache" "PS Eden Space" "PS Old Gen" "PS Survivor Space" "Compressed Class
Space" "Metaspace" | 在给定 JVM 内存池中分配的总字节数。仅在垃圾收集后更新,而不是持续更新。 |
| jvm_gc_collection_seconds_count | Summary | **gc**,包括:"PS
Scavenge" "PS MarkSweep"
| 在给定 JVM 垃圾收集器中花费的时间(以秒为单位) |
| jvm_gc_collection_seconds_sum | Summary | **gc**,包括:"PS
Scavenge" "PS MarkSweep"
| 在给定 JVM 垃圾收集器中花费的时间(以秒为单位)
-| jvm_info | Gauge |
**runtime**,例如:“Java(TM) SE Runtime Environment”。**供应商**,例如:“Oracle
Corporation”。**版本**,例如:“1.8.0_212-b10” | VM 版本信息
|
+| jvm_info | Gauge |
**runtime**,例如:“Java(TM) SE Runtime Environment”。**供应商**,例如:“Oracle
Corporation”。**版本**,例如:“11.0.22+7” | VM 版本信息
|
| process_cpu_seconds_total | Counter | -
| 用户和系统 CPU 时间总计,以秒为单位 |
| process_start_time_seconds | Gauge | -
| 进程自 Unix 纪元以来的启动时间,以秒为单位 |
| process_open_fds | Gauge | -
| 打开的文件描述符数量 |
diff --git a/docs/zh/getting-started/docker/docker.md
b/docs/zh/getting-started/docker/docker.md
index f637bf9067..85f76618e2 100644
--- a/docs/zh/getting-started/docker/docker.md
+++ b/docs/zh/getting-started/docker/docker.md
@@ -64,7 +64,7 @@ docker images | grep apache/seatunnel
Dockerfile文件内容为:
```dockerfile
-FROM seatunnelhub/openjdk:8u342
+FROM eclipse-temurin:11-jdk
ARG VERSION
# Build from Source Code And Copy it into image
@@ -394,4 +394,4 @@ docker run --name seatunnel_client \
更多其他命令请参考[命令行工具](../../engines/zeta/user-command.md)
#### 使用RestAPI
-请参考 [提交作业](../../engines/zeta/rest-api-v2.md#提交作业)
\ No newline at end of file
+请参考 [提交作业](../../engines/zeta/rest-api-v2.md#提交作业)
diff --git a/docs/zh/getting-started/kubernetes/kubernetes.mdx
b/docs/zh/getting-started/kubernetes/kubernetes.mdx
index cdc3e9894b..a4a69c0125 100644
--- a/docs/zh/getting-started/kubernetes/kubernetes.mdx
+++ b/docs/zh/getting-started/kubernetes/kubernetes.mdx
@@ -89,7 +89,7 @@ minikube start --kubernetes-version=v1.23.3
生产环境建议固定 SeaTunnel 镜像 tag,并将常用连接器、依赖和基础配置构建到镜像中,避免运行时下载依赖带来的不确定性。
```Dockerfile
-FROM seatunnelhub/openjdk:8u342
+FROM eclipse-temurin:11-jdk
ARG SEATUNNEL_VERSION
ENV SEATUNNEL_HOME="/opt/seatunnel"
diff --git a/docs/zh/getting-started/locally/deployment.md
b/docs/zh/getting-started/locally/deployment.md
index ef18f66b7b..ec18145c12 100644
--- a/docs/zh/getting-started/locally/deployment.md
+++ b/docs/zh/getting-started/locally/deployment.md
@@ -11,7 +11,7 @@ import TabItem from '@theme/TabItem';
在开始本地运行前,您需要确保您已经安装了SeaTunnel所需要的以下软件:
-* 安装[Java](https://www.java.com/en/download/) (Java 8 或 11, 其他高于Java
8的版本理论上也可以工作) 以及设置 `JAVA_HOME`。
+* 安装[Java](https://www.java.com/en/download/) (Java 11 或 Java 17) 以及设置
`JAVA_HOME`。
## 下载 SeaTunnel 发行包
diff --git a/docs/zh/getting-started/overview.md
b/docs/zh/getting-started/overview.md
index a3db40fa28..39a6e63bb6 100644
--- a/docs/zh/getting-started/overview.md
+++ b/docs/zh/getting-started/overview.md
@@ -60,7 +60,7 @@ SeaTunnel 是一个分布式数据集成平台,用统一的连接器模型处
## 开始之前需要准备什么
-- Java 8 或 Java 11,并正确设置 `JAVA_HOME`
+- Java 11 或 Java 17,并正确设置 `JAVA_HOME`
- 从 [下载页面](https://seatunnel.apache.org/download) 获取 SeaTunnel 二进制包
- 在 `${SEATUNNEL_HOME}/connectors/` 下安装所需插件
- 如果所选连接器依赖第三方驱动,还需要准备对应 jar 包
diff --git a/docs/zh/introduction/concepts/incompatible-changes.md
b/docs/zh/introduction/concepts/incompatible-changes.md
index 002cd6642e..cddfe214fe 100644
--- a/docs/zh/introduction/concepts/incompatible-changes.md
+++ b/docs/zh/introduction/concepts/incompatible-changes.md
@@ -4,6 +4,23 @@
## dev
+### 运行环境要求
+
+- **破坏性变更:最低 Java 运行时从 Java 8 提升到 Java 11**
+ - **影响范围**:所有模块——整个发行包、Zeta 引擎、全部连接器,以及发布的 Docker 镜像
+ - **变更说明**:构建目标改为 Java 11(`maven.compiler.source` 与 `maven.compiler.target`
均为 `11`),因此发布的每个 jar 的 class 文件版本都是 55。GitHub CI 基于该 Java 11 基线在 JDK 17
上编译和测试,发布的 Docker 镜像也从 `seatunnelhub/openjdk:8u342` 改为
`eclipse-temurin:11-jdk`——仍保留完整 JDK 而非 JRE,以便 `jps`/`jstack`/`jmap`
继续可用于诊断运行中的节点。
+ - **影响**:
+ - Java 8 JVM 无法再加载 SeaTunnel 的类,启动时会抛出
`java.lang.UnsupportedClassVersionError: ... has been compiled by a more recent
version of the Java Runtime (class file version 55.0)`。客户端、Zeta master 与 worker
节点,以及任何会加载连接器 jar 的进程都受此影响。
+ - **Flink**:JobManager 和 TaskManager 的 JVM 会加载 SeaTunnel 连接器类,因此整个 Flink
集群都必须运行 Java 11 及以上,而不只是提交作业的客户端。Flink 从 1.13 起支持 Java 11,官方 Flink 镜像提供
`-java11` 标签。
+ - **Spark**:Driver 和 Executor 的 JVM 会加载 SeaTunnel 连接器类,因此整个 Spark 集群都必须运行
Java 11 及以上。Spark 从 3.0 起才正式支持 Java 11(SPARK-24417)。Spark 2.4 在 Java 11
上仍可启动,但会打印非法反射访问告警,并且会把较老的 commons-lang3 放进 classpath,部分连接器会因此初始化失败,因此强烈建议使用
Spark 3.x。
+ - 已按 Java 8 编译的第三方连接器仍可正常使用。Java 11 JVM 可以直接加载更低版本的 class 文件,所以只有 JVM
版本有要求,对您自己 jar 的字节码级别没有要求。
+ - **迁移指南**:
+ 1. 将所有运行 SeaTunnel 代码的节点的 JVM 升级到 Java 11 或 Java 17:客户端、Zeta master 与
worker,以及作业提交到的 Flink 或 Spark 集群。
+ 2. 如果提交到 Flink,请将集群切换到运行 Java 11 及以上的镜像或部署。
+ 3. 如果提交到 Spark 2.4,请升级到运行在 Java 11 及以上的 Spark 3.x。Spark 2.x 没有任何版本支持 Java
11。
+ 4. 如果您修改过 `${SEATUNNEL_HOME}/config/jvm_options`(以及 client、master、worker
对应的变体),请检查自己添加的参数中是否包含 Java 11 已移除的选项,例如 `-XX:+UseConcMarkSweepGC` 或
`-XX:MaxPermSize`,JVM 遇到无法识别的参数会直接拒绝启动。发行包默认提供的参数已经兼容 Java 11。
+ 5. 无需把新增的 JDK 模块参数手工复制到保留下来的配置目录中。`seatunnel.sh` 和 `seatunnel-cluster.sh`
会自行追加必需的 `--add-opens`/`--add-exports`
参数(`java.base/java.lang`、`java.net`、`java.nio`、`java.util`、`sun.nio.ch`,以及
`java.security.jgss/sun.security.krb5`),并跳过您的 `jvm_*_options`
中已有的同名参数,因此原地升级并保留旧的 `config/` 目录(挂载的 Docker 卷或 Kubernetes
ConfigMap)时,这些参数依然生效。当检测到的 JVM 版本低于 11 时,同样的脚本会直接以明确的 `SeaTunnel requires Java
11 or newer` 提示退出,而不是让 Java 8 启动器输出原始的 `Unrecognized option` 错误。
+
### SQL TINYINT 数组模式
Zeta SQL ARRAY 函数现在将 TINYINT 元素声明为 `ARRAY<TINYINT>`,与实际输出的 Byte 值一致。此前错误的
`ARRAY<STRING>` 声明会导致依赖模式的行处理失败。请更新假定元素为 STRING 的下游声明;需要字符串模式时,在 SQL 中显式将值转换为
STRING。受影响的作业应使用修正后的模式重新启动,不要恢复依赖旧声明的状态。
diff --git a/pom.xml b/pom.xml
index baf66a1ff9..831aac0e4d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -77,11 +77,16 @@
<seatunnel.shade.calcite.version>1.38.0</seatunnel.shade.calcite.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <java.version>1.8</java.version>
+ <java.version>11</java.version>
<scala.version>2.12.15</scala.version>
<scala.binary.version>2.12</scala.binary.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
+ <!-- Constrains javac to the API surface of java.version, not merely
its bytecode level,
+ so compiling on a JDK newer than java.version cannot silently
link against APIs the
+ target runtime does not have. Modules that must still output Java
8 bytecode override
+ this property (not source/target, which the compiler plugin below
no longer reads). -->
+ <maven.compiler.release>${java.version}</maven.compiler.release>
<system-rules.version>1.2.1</system-rules.version>
<powermock.version>2.0.9</powermock.version>
@@ -166,6 +171,19 @@
<hugegraph.client.version>1.7.0</hugegraph.client.version>
<!-- Option args -->
<surefire.jvm.args>-Dfile.encoding=UTF-8</surefire.jvm.args>
+ <!--
+ JDK 9+ dropped default reflective access to several JDK internals
that Hazelcast (the
+ Zeta engine's runtime) and this project's own reflective
Kerberos/classloader helpers
+ depend on; see the comments in config/jvm_options for the per-flag
rationale. Test JVMs
+ forked by Surefire/Failsafe need the same flags the launcher
scripts inject for a real
+ cluster. They live in their own property, separate from
surefire.jvm.args, so a CLI
+ override such as -Dsurefire.jvm.args=-Xmx3g (used by the unit-test
CI lane) cannot
+ silently drop them, and in a plain property rather than a
JDK-activated profile because
+ activating any profile by <jdk> deactivates the activeByDefault
"release" profile and
+ silently removes seatunnel-dist from the default reactor. Java 11
is the compile
+ baseline (maven.compiler.release), so the flags are always valid
and need no JDK gate.
+ -->
+ <surefire.module.args>--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.net=ALL-UNNAMED
--add-opens=java.base/java.nio=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED</surefire.module.args>
<skipUT>false</skipUT>
<skipIT>true</skipIT>
<elasticsearch>7</elasticsearch>
@@ -768,8 +786,7 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
- <source>${maven.compiler.source}</source>
- <target>${maven.compiler.target}</target>
+ <release>${maven.compiler.release}</release>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
</configuration>
</plugin>
@@ -778,7 +795,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
- <argLine>${surefire.jvm.args}</argLine>
+ <argLine>${surefire.jvm.args}
${surefire.module.args}</argLine>
<skip>${skipUT}</skip>
<systemPropertyVariables>
<jacoco-agent.destfile>${project.build.directory}/jacoco.exec</jacoco-agent.destfile>
@@ -810,7 +827,7 @@
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<configuration>
- <argLine>${surefire.jvm.args}</argLine>
+ <argLine>${surefire.jvm.args}
${surefire.module.args}</argLine>
<skip>${skipIT}</skip>
</configuration>
<executions>
diff --git a/seatunnel-ci-tools/pom.xml b/seatunnel-ci-tools/pom.xml
index 783d263ba7..136dc8bddc 100644
--- a/seatunnel-ci-tools/pom.xml
+++ b/seatunnel-ci-tools/pom.xml
@@ -50,8 +50,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
- <source>8</source>
- <target>8</target>
+ <release>8</release>
</configuration>
</plugin>
</plugins>
diff --git
a/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/exception/EdgeSocketConnectorErrorCode.java
b/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/exception/EdgeSocketConnectorErrorCode.java
index 1861682383..5dd61b2073 100644
---
a/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/exception/EdgeSocketConnectorErrorCode.java
+++
b/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/exception/EdgeSocketConnectorErrorCode.java
@@ -30,7 +30,8 @@ public enum EdgeSocketConnectorErrorCode implements
SeaTunnelErrorCode {
PACKET_AES_KEY_MISSING("EDGE_SOCKET-08", "Missing secret_key for AES_GCM
packet"),
COLLECTOR_REJECTED(
"EDGE_SOCKET-09",
- "Rejected collector connection because another collector is
already connected");
+ "Rejected collector connection because another collector is
already connected"),
+ PACKET_DECRYPT_ERROR("EDGE_SOCKET-10", "Failed to decrypt ingress packet");
private final String code;
private final String description;
diff --git
a/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/serialize/record/EdgeSocketPacketRecordDeserializer.java
b/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/serialize/record/EdgeSocketPacketRecordDeserializer.java
index 265a80464c..af6021547d 100644
---
a/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/serialize/record/EdgeSocketPacketRecordDeserializer.java
+++
b/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/serialize/record/EdgeSocketPacketRecordDeserializer.java
@@ -32,6 +32,7 @@ import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.GeneralSecurityException;
+import java.security.ProviderException;
import java.util.Base64;
public class EdgeSocketPacketRecordDeserializer implements
EdgeSocketRecordDeserializer {
@@ -104,16 +105,24 @@ public class EdgeSocketPacketRecordDeserializer
implements EdgeSocketRecordDeser
EdgeSocketConnectorErrorCode.PACKET_DECODE_ERROR,
"Missing iv in AES_GCM packet");
}
+ byte[] iv;
+ try {
+ iv = Base64.getDecoder().decode(packet.getIv());
+ } catch (IllegalArgumentException invalidIvException) {
+ throw new EdgeSocketConnectorException(
+ EdgeSocketConnectorErrorCode.PACKET_DECODE_ERROR,
+ "Decode AES_GCM iv failed",
+ invalidIvException);
+ }
try {
- byte[] iv = Base64.getDecoder().decode(packet.getIv());
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec key = new SecretKeySpec(config.getSecretKeyBytes(),
"AES");
cipher.init(
Cipher.DECRYPT_MODE, key, new
GCMParameterSpec(AES_GCM_TAG_LENGTH_BITS, iv));
return cipher.doFinal(payloadBytes);
- } catch (GeneralSecurityException securityException) {
+ } catch (GeneralSecurityException | ProviderException
securityException) {
throw new EdgeSocketConnectorException(
- EdgeSocketConnectorErrorCode.PACKET_DECODE_ERROR,
+ EdgeSocketConnectorErrorCode.PACKET_DECRYPT_ERROR,
"AES_GCM decrypt failed",
securityException);
}
diff --git
a/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/source/EdgeSocketSourceReader.java
b/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/source/EdgeSocketSourceReader.java
index f914b4e96e..ec495ea6df 100644
---
a/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/source/EdgeSocketSourceReader.java
+++
b/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/source/EdgeSocketSourceReader.java
@@ -224,7 +224,6 @@ public class EdgeSocketSourceReader extends
AbstractSingleSplitReader<SeaTunnelR
EdgeSocketConnectorErrorCode errorCode =
(EdgeSocketConnectorErrorCode)
exception.getSeaTunnelErrorCode();
return errorCode == EdgeSocketConnectorErrorCode.PACKET_AES_KEY_MISSING
- || (errorCode ==
EdgeSocketConnectorErrorCode.PACKET_DECODE_ERROR
- && exception.getCause() instanceof
java.security.GeneralSecurityException);
+ || errorCode ==
EdgeSocketConnectorErrorCode.PACKET_DECRYPT_ERROR;
}
}
diff --git a/seatunnel-connectors-v2/connector-fluss/pom.xml
b/seatunnel-connectors-v2/connector-fluss/pom.xml
index 8db032b6f9..b66f8184bd 100644
--- a/seatunnel-connectors-v2/connector-fluss/pom.xml
+++ b/seatunnel-connectors-v2/connector-fluss/pom.xml
@@ -46,6 +46,43 @@
<artifactId>fluss-client</artifactId>
<version>${fluss.client.version}</version>
</dependency>
+ <!--
+ fluss-client calls
org.apache.commons.lang3.SystemUtils.isJavaVersionAtLeast, which
+ returns null from JavaVersion.get(...) and then throws NPE on
runtimes the bundled
+ commons-lang3 predates. Spark 2.4 puts commons-lang3 3.5 on the
classpath, so on
+ Java 11 the Fluss source and sink fail to initialise. Pin a
version that knows modern
+ Java and relocate it below so the engine's own copy cannot win.
+ -->
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>${commons-lang3.version}</version>
+ </dependency>
</dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <relocations>
+ <relocation>
+ <pattern>org.apache.commons.lang3</pattern>
+
<shadedPattern>${seatunnel.shade.package}.fluss.org.apache.commons.lang3</shadedPattern>
+ </relocation>
+ </relocations>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
</project>
diff --git a/seatunnel-connectors-v2/connector-iceberg/pom.xml
b/seatunnel-connectors-v2/connector-iceberg/pom.xml
index 411bc8ae60..c30bb45c70 100644
--- a/seatunnel-connectors-v2/connector-iceberg/pom.xml
+++ b/seatunnel-connectors-v2/connector-iceberg/pom.xml
@@ -110,6 +110,12 @@
<artifactId>orc-core</artifactId>
<version>1.7.5</version>
<classifier>nohive</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-client-api</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.apache.iceberg</groupId>
diff --git
a/seatunnel-connectors-v2/connector-kudu/src/main/java/org/apache/seatunnel/connectors/seatunnel/kudu/util/KuduUtil.java
b/seatunnel-connectors-v2/connector-kudu/src/main/java/org/apache/seatunnel/connectors/seatunnel/kudu/util/KuduUtil.java
index 4b1f4239d5..462ead3054 100644
---
a/seatunnel-connectors-v2/connector-kudu/src/main/java/org/apache/seatunnel/connectors/seatunnel/kudu/util/KuduUtil.java
+++
b/seatunnel-connectors-v2/connector-kudu/src/main/java/org/apache/seatunnel/connectors/seatunnel/kudu/util/KuduUtil.java
@@ -40,8 +40,6 @@ import org.apache.kudu.client.KuduScanToken;
import org.apache.kudu.client.KuduTable;
import lombok.extern.slf4j.Slf4j;
-import sun.security.krb5.Config;
-import sun.security.krb5.KrbException;
import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosPrincipal;
@@ -146,12 +144,33 @@ public class KuduUtil {
private static void reloadKrb5conf(String krb5conf) {
System.setProperty(KRB5_CONF_KEY, krb5conf);
+ refreshJdkKerberosConfig();
+ KerberosName.resetDefaultRealm();
+ }
+
+ /**
+ * Refresh the JDK Kerberos configuration without a compile-time
dependency on internal JDK
+ * packages. Directly importing sun.security.krb5.Config breaks Java 17
compilation because the
+ * package is not exported by the java.security.jgss module.
+ */
+ private static void refreshJdkKerberosConfig() {
try {
- Config.refresh();
- KerberosName.resetDefaultRealm();
- } catch (KrbException e) {
+
Class.forName("sun.security.krb5.Config").getMethod("refresh").invoke(null);
+ } catch (IllegalAccessException e) {
+ // Module access denied: the JVM is missing the jgss export, so
the custom krb5.conf
+ // configured for this source cannot take effect. This is an
actionable deployment
+ // problem, not a transient refresh failure, so report it at ERROR
with the fix.
+ log.error(
+ "JVM module system denied the Kerberos configuration
reload, so the configured"
+ + " krb5.conf will NOT take effect. Start the JVM
with"
+ + "
--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED"
+ + " (shipped in config/jvm_*_options and appended
by the launch"
+ + " scripts since the Java 11 baseline).",
+ e);
+ } catch (ReflectiveOperationException | RuntimeException e) {
log.warn(
- "resetting default realm failed, current default realm
will still be used.", e);
+ "refreshing JDK Kerberos configuration failed, current
default realm will still be used.",
+ e);
}
}
diff --git
a/seatunnel-connectors-v2/connector-paimon/src/main/java/org/apache/seatunnel/connectors/seatunnel/paimon/security/PaimonSecurityContext.java
b/seatunnel-connectors-v2/connector-paimon/src/main/java/org/apache/seatunnel/connectors/seatunnel/paimon/security/PaimonSecurityContext.java
index 03decec17e..2b24527c3e 100644
---
a/seatunnel-connectors-v2/connector-paimon/src/main/java/org/apache/seatunnel/connectors/seatunnel/paimon/security/PaimonSecurityContext.java
+++
b/seatunnel-connectors-v2/connector-paimon/src/main/java/org/apache/seatunnel/connectors/seatunnel/paimon/security/PaimonSecurityContext.java
@@ -34,8 +34,6 @@ import org.apache.paimon.security.SecurityConfiguration;
import org.apache.paimon.security.SecurityContext;
import lombok.extern.slf4j.Slf4j;
-import sun.security.krb5.Config;
-import sun.security.krb5.KrbException;
import java.io.IOException;
import java.nio.file.Files;
@@ -141,11 +139,34 @@ public class PaimonSecurityContext extends
SecurityContext {
private static void reloadKrb5conf(String krb5conf) {
System.setProperty(KRB5_CONF_KEY, krb5conf);
try {
- Config.refresh();
+ refreshJdkKerberosConfig();
KerberosName.resetDefaultRealm();
- } catch (KrbException e) {
+ } catch (IllegalAccessException e) {
+ // Module access denied: the JVM is missing the jgss export, so
the custom krb5.conf
+ // configured for this catalog cannot take effect. This is an
actionable deployment
+ // problem, not a transient refresh failure, so report it at ERROR
with the fix.
+ log.error(
+ "JVM module system denied the Kerberos configuration
reload, so the configured"
+ + " krb5.conf will NOT take effect. Start the JVM
with"
+ + "
--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED"
+ + " (shipped in config/jvm_*_options and appended
by the launch"
+ + " scripts since the Java 11 baseline).",
+ e);
+ } catch (ReflectiveOperationException e) {
log.warn(
"resetting default realm failed, current default realm
will still be used.", e);
}
}
+
+ /**
+ * Refreshes the JDK Kerberos configuration so that the krb5.conf just set
takes effect.
+ *
+ * <p>Invoked reflectively because sun.security.krb5.Config lives in the
java.security.jgss
+ * module, which does not export it to the unnamed module, so importing it
directly fails to
+ * compile on Java 17. A failure here leaves the default realm untouched,
which matches the
+ * previous behaviour when Config.refresh() threw.
+ */
+ private static void refreshJdkKerberosConfig() throws
ReflectiveOperationException {
+
Class.forName("sun.security.krb5.Config").getMethod("refresh").invoke(null);
+ }
}
diff --git a/seatunnel-core/seatunnel-starter/src/main/bin/seatunnel-cluster.sh
b/seatunnel-core/seatunnel-starter/src/main/bin/seatunnel-cluster.sh
index 2a91905026..a18431c518 100755
--- a/seatunnel-core/seatunnel-starter/src/main/bin/seatunnel-cluster.sh
+++ b/seatunnel-core/seatunnel-starter/src/main/bin/seatunnel-cluster.sh
@@ -154,6 +154,32 @@ do
fi
done
+# SeaTunnel requires Java 11 or newer. Fail fast with an actionable message
instead of letting a
+# JDK 8 launcher abort on the JDK 9+ module flags below with a cryptic
"Unrecognized option" error.
+JAVA_MAJOR_VERSION=$(java -version 2>&1 | awk -F '[".]' '/version/ {print ($2
== "1") ? $3 : $2; exit}')
+if [[ -n "$JAVA_MAJOR_VERSION" && "$JAVA_MAJOR_VERSION" -lt 11 ]]; then
+ echo "Error: SeaTunnel requires Java 11 or newer, but Java
${JAVA_MAJOR_VERSION} was detected. Point JAVA_HOME/PATH at a Java 11+ JDK." >&2
+ exit 1
+fi
+
+# These JDK module flags are mandatory on Java 11+: Hazelcast needs reflective
access to JDK
+# internals and the Kerberos krb5.conf reload needs the jgss export. They are
appended here, not
+# only shipped in the config/jvm_*_options templates, so an in-place upgrade
that preserves an old
+# config directory (mounted Docker volume, K8s ConfigMap) cannot silently drop
them. Appending a
+# flag twice is harmless, so config files that already carry them stay
compatible.
+for module_flag in \
+ "--add-opens=java.base/java.lang=ALL-UNNAMED" \
+ "--add-opens=java.base/java.net=ALL-UNNAMED" \
+ "--add-opens=java.base/java.nio=ALL-UNNAMED" \
+ "--add-opens=java.base/java.util=ALL-UNNAMED" \
+ "--add-opens=java.base/sun.nio.ch=ALL-UNNAMED" \
+ "--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED"; do
+ case " ${JAVA_OPTS} " in
+ *" ${module_flag} "*) ;;
+ *) JAVA_OPTS="${JAVA_OPTS} ${module_flag}" ;;
+ esac
+done
+
# Ensure HeapDumpPath directory exists to avoid OOM dump failures.
HEAP_DUMP_PATH=""
diff --git
a/seatunnel-core/seatunnel-starter/src/main/bin/seatunnel-connector.sh
b/seatunnel-core/seatunnel-starter/src/main/bin/seatunnel-connector.sh
index 92dfa3d275..1b30aad5ae 100755
--- a/seatunnel-core/seatunnel-starter/src/main/bin/seatunnel-connector.sh
+++ b/seatunnel-core/seatunnel-starter/src/main/bin/seatunnel-connector.sh
@@ -48,4 +48,18 @@ fi
set +u
CLASS_PATH=${APP_DIR}/connectors/*:${APP_JAR}:${APP_DIR}/lib/seatunnel-transforms-v2.jar
-java -cp ${CLASS_PATH} ${LOAD_CLASS} ${args} | grep -v
'org\.apache\.seatunnel\.plugin\.discovery\.AbstractPluginDiscovery'
+# The second pattern drops the notice log4j-api writes to stdout on every JVM
newer than Java 8,
+# which would otherwise be parsed as extra connector identifiers by the
connector check output.
+#
+# set -e is active from the top of the script, and grep exits 1 when it emits
no lines at all, so
+# the pipeline has to run with errexit off or an empty connector list would
abort the script before
+# the exit below. PIPESTATUS[0] then reports java's own status rather than
grep's, which previously
+# let a failing java run be reported as success.
+set +e
+java -cp ${CLASS_PATH} ${LOAD_CLASS} ${args} \
+ | grep -v --line-buffered \
+ -e
'org\.apache\.seatunnel\.plugin\.discovery\.AbstractPluginDiscovery' \
+ -e '^WARNING: sun\.reflect\.Reflection\.getCallerClass is not
supported'
+JAVA_EXIT_CODE=${PIPESTATUS[0]}
+set -e
+exit ${JAVA_EXIT_CODE}
diff --git a/seatunnel-core/seatunnel-starter/src/main/bin/seatunnel.sh
b/seatunnel-core/seatunnel-starter/src/main/bin/seatunnel.sh
index 7af0c149eb..a88704b57b 100755
--- a/seatunnel-core/seatunnel-starter/src/main/bin/seatunnel.sh
+++ b/seatunnel-core/seatunnel-starter/src/main/bin/seatunnel.sh
@@ -109,6 +109,32 @@ do
fi
done
+# SeaTunnel requires Java 11 or newer. Fail fast with an actionable message
instead of letting a
+# JDK 8 launcher abort on the JDK 9+ module flags below with a cryptic
"Unrecognized option" error.
+JAVA_MAJOR_VERSION=$(java -version 2>&1 | awk -F '[".]' '/version/ {print ($2
== "1") ? $3 : $2; exit}')
+if [[ -n "$JAVA_MAJOR_VERSION" && "$JAVA_MAJOR_VERSION" -lt 11 ]]; then
+ echo "Error: SeaTunnel requires Java 11 or newer, but Java
${JAVA_MAJOR_VERSION} was detected. Point JAVA_HOME/PATH at a Java 11+ JDK." >&2
+ exit 1
+fi
+
+# These JDK module flags are mandatory on Java 11+: Hazelcast needs reflective
access to JDK
+# internals and the Kerberos krb5.conf reload needs the jgss export. They are
appended here, not
+# only shipped in the config/jvm_*_options templates, so an in-place upgrade
that preserves an old
+# config directory (mounted Docker volume, K8s ConfigMap) cannot silently drop
them. Appending a
+# flag twice is harmless, so config files that already carry them stay
compatible.
+for module_flag in \
+ "--add-opens=java.base/java.lang=ALL-UNNAMED" \
+ "--add-opens=java.base/java.net=ALL-UNNAMED" \
+ "--add-opens=java.base/java.nio=ALL-UNNAMED" \
+ "--add-opens=java.base/java.util=ALL-UNNAMED" \
+ "--add-opens=java.base/sun.nio.ch=ALL-UNNAMED" \
+ "--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED"; do
+ case " ${JAVA_OPTS} " in
+ *" ${module_flag} "*) ;;
+ *) JAVA_OPTS="${JAVA_OPTS} ${module_flag}" ;;
+ esac
+done
+
# Ensure HeapDumpPath directory exists to avoid OOM dump failures.
HEAP_DUMP_PATH=""
for opt in $JAVA_OPTS; do
@@ -146,4 +172,17 @@ if [[ -n "$GC_LOG_PATH" ]]; then
fi
fi
-java ${JAVA_OPTS} -cp ${CLASS_PATH} ${APP_MAIN} "${args[@]}"
+# log4j-api writes this notice to stdout on every JVM newer than Java 8,
because
+# sun.reflect.Reflection.getCallerClass no longer exists there. It corrupts
the machine readable
+# output of commands that emit JSON, such as `-j <jobId>`, so drop just that
line.
+#
+# set -e is active from the top of the script, and grep exits 1 when it emits
no lines at all, so
+# the pipeline has to run with errexit off or a command with empty stdout
would abort the script
+# before the exit below. PIPESTATUS[0] then reports java's own status rather
than grep's.
+# --line-buffered keeps job output streaming when stdout is redirected to a
file.
+set +e
+java ${JAVA_OPTS} -cp ${CLASS_PATH} ${APP_MAIN} "${args[@]}" \
+ | grep -v --line-buffered '^WARNING:
sun\.reflect\.Reflection\.getCallerClass is not supported'
+JAVA_EXIT_CODE=${PIPESTATUS[0]}
+set -e
+exit ${JAVA_EXIT_CODE}
diff --git
a/seatunnel-core/seatunnel-starter/src/main/java/org/apache/seatunnel/core/starter/seatunnel/command/ServerExecuteCommand.java
b/seatunnel-core/seatunnel-starter/src/main/java/org/apache/seatunnel/core/starter/seatunnel/command/ServerExecuteCommand.java
index 7bf728bce0..0eceb20e56 100644
---
a/seatunnel-core/seatunnel-starter/src/main/java/org/apache/seatunnel/core/starter/seatunnel/command/ServerExecuteCommand.java
+++
b/seatunnel-core/seatunnel-starter/src/main/java/org/apache/seatunnel/core/starter/seatunnel/command/ServerExecuteCommand.java
@@ -40,8 +40,6 @@ import lombok.extern.slf4j.Slf4j;
import java.util.Collection;
import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
/** This command is used to execute the SeaTunnel engine job by SeaTunnel API.
*/
@Slf4j
@@ -85,31 +83,15 @@ public class ServerExecuteCommand implements
Command<ServerCommandArgs> {
}
private void checkEnvironment() {
- if (isAllocatingThreadGetName()) {
+ if (isUnsupportedJavaVersion()) {
log.warn(
- "The current JDK version is not recommended. Please
upgrade to JDK 1.8.0_102 or higher. "
- + "The current version will affect the performance
of log printing. "
- + "For details, please refer to
https://issues.apache.org/jira/browse/LOG4J2-2052");
+ "The current JDK version is not supported. "
+ + "Please use JDK 11 or JDK 17 to run SeaTunnel.");
}
}
- static boolean isAllocatingThreadGetName() {
- // LOG4J2-2052, LOG4J2-2635 JDK 8u102 ("1.8.0_102") removed the String
allocation in
- // Thread.getName()
- if (SystemUtils.IS_JAVA_1_8) {
- try {
- Pattern javaVersionPattern =
Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)_(\\d+)");
- Matcher m =
javaVersionPattern.matcher(System.getProperty("java.version"));
- if (m.matches()) {
- return Integer.parseInt(m.group(3)) == 0 &&
Integer.parseInt(m.group(4)) < 102;
- }
- return true;
- } catch (Exception e) {
- return true;
- }
- } else {
- return !SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8);
- }
+ static boolean isUnsupportedJavaVersion() {
+ return !SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_11);
}
@VisibleForTesting
diff --git
a/seatunnel-core/seatunnel-starter/src/test/java/org/apache/seatunnel/core/starter/seatunnel/command/ServerExecuteCommandTest.java
b/seatunnel-core/seatunnel-starter/src/test/java/org/apache/seatunnel/core/starter/seatunnel/command/ServerExecuteCommandTest.java
index 78b7d06b7f..d32d942e14 100644
---
a/seatunnel-core/seatunnel-starter/src/test/java/org/apache/seatunnel/core/starter/seatunnel/command/ServerExecuteCommandTest.java
+++
b/seatunnel-core/seatunnel-starter/src/test/java/org/apache/seatunnel/core/starter/seatunnel/command/ServerExecuteCommandTest.java
@@ -24,7 +24,7 @@ import
org.apache.seatunnel.engine.server.SeaTunnelServerStarter;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.DisabledOnJre;
+import org.junit.jupiter.api.condition.EnabledOnJre;
import org.junit.jupiter.api.condition.JRE;
import com.hazelcast.cluster.Member;
@@ -37,17 +37,9 @@ import java.util.Set;
public class ServerExecuteCommandTest {
@Test
- @DisabledOnJre(value = JRE.JAVA_11, disabledReason = "the test case only
works on Java 8")
- public void testJavaVersionCheck() {
- String realVersion = System.getProperty("java.version");
- try {
- System.setProperty("java.version", "1.8.0_191");
-
Assertions.assertFalse(ServerExecuteCommand.isAllocatingThreadGetName());
- System.setProperty("java.version", "1.8.0_60");
-
Assertions.assertTrue(ServerExecuteCommand.isAllocatingThreadGetName());
- } finally {
- System.setProperty("java.version", realVersion);
- }
+ @EnabledOnJre(value = {JRE.JAVA_11, JRE.JAVA_17})
+ public void testSupportedJavaVersionCheck() {
+
Assertions.assertFalse(ServerExecuteCommand.isUnsupportedJavaVersion());
}
@Test
diff --git a/seatunnel-dist/src/main/docker/Dockerfile
b/seatunnel-dist/src/main/docker/Dockerfile
index aa9a7769c9..44cfdf9afc 100644
--- a/seatunnel-dist/src/main/docker/Dockerfile
+++ b/seatunnel-dist/src/main/docker/Dockerfile
@@ -1,4 +1,4 @@
-FROM seatunnelhub/openjdk:8u342 as builder
+FROM eclipse-temurin:11-jdk as builder
ARG VERSION
@@ -12,6 +12,9 @@ RUN cd /opt && \
sed -i
's/rootLogger.appenderRef.file.ref/#rootLogger.appenderRef.file.ref/'
seatunnel/config/log4j2.properties && \
cp seatunnel/config/hazelcast-master.yaml
seatunnel/config/hazelcast-worker.yaml
-FROM seatunnelhub/openjdk:8u342
+FROM eclipse-temurin:11-jdk
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends python3 \
+ && rm -rf /var/lib/apt/lists/*
COPY --from=builder /opt/seatunnel /opt/seatunnel
WORKDIR /opt/seatunnel
diff --git
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-amazondynamodb-e2e/src/test/java/org/apache/seatunnel/e2e/connector/amazondynamodb/AmazondynamodbIT.java
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-amazondynamodb-e2e/src/test/java/org/apache/seatunnel/e2e/connector/amazondynamodb/AmazondynamodbIT.java
index da4448410e..1a2afbdca6 100644
---
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-amazondynamodb-e2e/src/test/java/org/apache/seatunnel/e2e/connector/amazondynamodb/AmazondynamodbIT.java
+++
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-amazondynamodb-e2e/src/test/java/org/apache/seatunnel/e2e/connector/amazondynamodb/AmazondynamodbIT.java
@@ -68,6 +68,7 @@ import java.net.ConnectException;
import java.net.URI;
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -268,7 +269,7 @@ public class AmazondynamodbIT extends TestSuiteBase
implements TestResource {
BigDecimal.valueOf(11, 1),
"test".getBytes(),
LocalDate.now(),
- LocalDateTime.now()
+ LocalDateTime.now().truncatedTo(ChronoUnit.MICROS)
});
Map<String, AttributeValue> data = new
HashMap<>(seatunnelRowType.getTotalFields());
diff --git
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-cdc-tidb-e2e/pom.xml
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-cdc-tidb-e2e/pom.xml
index b0446e6701..32025682c7 100644
--- a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-cdc-tidb-e2e/pom.xml
+++ b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-cdc-tidb-e2e/pom.xml
@@ -28,6 +28,7 @@
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
+ <maven.compiler.release>8</maven.compiler.release>
</properties>
<dependencies>
diff --git
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fluss-e2e/pom.xml
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fluss-e2e/pom.xml
index 4105b14d24..b0c9f3ab81 100644
--- a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fluss-e2e/pom.xml
+++ b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-fluss-e2e/pom.xml
@@ -72,8 +72,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
- <source>8</source>
- <target>8</target>
+ <release>8</release>
</configuration>
</plugin>
</plugins>
diff --git
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-python-e2e/src/test/java/org/apache/seatunnel/e2e/connector/python/PythonIT.java
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-python-e2e/src/test/java/org/apache/seatunnel/e2e/connector/python/PythonIT.java
index 7165ecef43..6b2d8892a1 100644
---
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-python-e2e/src/test/java/org/apache/seatunnel/e2e/connector/python/PythonIT.java
+++
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-python-e2e/src/test/java/org/apache/seatunnel/e2e/connector/python/PythonIT.java
@@ -37,11 +37,17 @@ import java.io.IOException;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class PythonIT extends SeaTunnelContainer {
+ private static final String PYTHON_EXECUTABLE_ALLOWLIST =
+
"/usr/bin/python3,/usr/local/bin/python3,/opt/bitnami/python/bin/python3,"
+ + "/usr/bin/python,/usr/local/bin/python";
+
@Override
protected String[] buildStartCommand() {
return new String[] {
"env",
- "JAVA_TOOL_OPTIONS=-Dseatunnel.source.python.enabled=true
-Dseatunnel.source.python.allowed-executables=/usr/bin/python3",
+ "JAVA_TOOL_OPTIONS=-Dseatunnel.source.python.enabled=true"
+ + " -Dseatunnel.source.python.allowed-executables="
+ + PYTHON_EXECUTABLE_ALLOWLIST,
super.buildStartCommand()[0]
};
}
@@ -50,6 +56,8 @@ public class PythonIT extends SeaTunnelContainer {
@BeforeAll
public void startUp() throws Exception {
super.startUp();
+ Container.ExecResult execResult = installPythonIfNecessary();
+ Assertions.assertEquals(0, execResult.getExitCode(),
execResult.getStderr());
copyFileToContainer("/python/emit_rows.py", "/tmp/emit_rows.py");
}
@@ -67,4 +75,29 @@ public class PythonIT extends SeaTunnelContainer {
Container.ExecResult result = executeJob("/python_to_assert.conf");
Assertions.assertEquals(0, result.getExitCode(), result.getStderr());
}
+
+ /** Installs python3 in the shared runtime container when the base image
does not include it. */
+ private Container.ExecResult installPythonIfNecessary()
+ throws IOException, InterruptedException {
+ return server.execInContainer(
+ "bash",
+ "-c",
+ "if command -v python3 >/dev/null 2>&1; then"
+ + " python3 --version;"
+ + " elif command -v apt-get >/dev/null 2>&1; then"
+ + " export DEBIAN_FRONTEND=noninteractive;"
+ + " apt-get update;"
+ + " apt-get install -y --no-install-recommends
python3;"
+ + " elif command -v dnf >/dev/null 2>&1; then"
+ + " dnf install -y python3;"
+ + " elif command -v yum >/dev/null 2>&1; then"
+ + " yum install -y python3;"
+ + " elif command -v apk >/dev/null 2>&1; then"
+ + " apk add --no-cache python3;"
+ + " else"
+ + " echo 'Unsupported package manager for installing
python3' >&2;"
+ + " exit 1;"
+ + " fi;"
+ + " python3 --version;");
+ }
}
diff --git
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-python-e2e/src/test/resources/python_to_assert.conf
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-python-e2e/src/test/resources/python_to_assert.conf
index 8bc7dbaa22..91cedb5589 100644
---
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-python-e2e/src/test/resources/python_to_assert.conf
+++
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-python-e2e/src/test/resources/python_to_assert.conf
@@ -23,7 +23,7 @@ env {
source {
Python {
plugin_output = "python_source"
- python.executable = "/usr/bin/python3"
+ python.executable = "python3"
python.script.path = "/tmp/emit_rows.py"
python.working.directory = "/tmp"
python.script.config = {
diff --git
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rabbitmq-e2e/src/test/java/org/apache/seatunnel/e2e/connector/rabbitmq/RabbitmqIT.java
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rabbitmq-e2e/src/test/java/org/apache/seatunnel/e2e/connector/rabbitmq/RabbitmqIT.java
index 3444edd01d..2c3ea073ef 100644
---
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rabbitmq-e2e/src/test/java/org/apache/seatunnel/e2e/connector/rabbitmq/RabbitmqIT.java
+++
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-rabbitmq-e2e/src/test/java/org/apache/seatunnel/e2e/connector/rabbitmq/RabbitmqIT.java
@@ -81,6 +81,7 @@ import java.nio.file.Path;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -374,7 +375,7 @@ public class RabbitmqIT extends TestSuiteBase implements
TestResource {
BigDecimal.valueOf(11, 1),
"test".getBytes(),
LocalDate.now(),
- LocalDateTime.now()
+
LocalDateTime.now().truncatedTo(ChronoUnit.MICROS)
});
rows.add(row);
}
diff --git
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-tdengine-e2e/pom.xml
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-tdengine-e2e/pom.xml
index 04e6744e34..3c27ff77a9 100644
--- a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-tdengine-e2e/pom.xml
+++ b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-tdengine-e2e/pom.xml
@@ -28,6 +28,7 @@
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
+ <maven.compiler.release>8</maven.compiler.release>
</properties>
<dependencies>
<!-- SeaTunnel connectors -->
diff --git
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-typesense-e2e/pom.xml
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-typesense-e2e/pom.xml
index 0a7243ed6a..e544f5a66a 100644
--- a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-typesense-e2e/pom.xml
+++ b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-typesense-e2e/pom.xml
@@ -30,6 +30,7 @@
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
+ <maven.compiler.release>8</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/docker/spark/Dockerfile
b/seatunnel-e2e/seatunnel-e2e-common/src/test/docker/spark/Dockerfile
index b7c7a13c6c..1218d5f0b5 100644
--- a/seatunnel-e2e/seatunnel-e2e-common/src/test/docker/spark/Dockerfile
+++ b/seatunnel-e2e/seatunnel-e2e-common/src/test/docker/spark/Dockerfile
@@ -14,7 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-FROM eclipse-temurin:8-jre-jammy
+# A full JDK, not a JRE, to match the rest of this project's E2E engine
images: ContainerUtil
+# execs jps/jstack/jmap into running containers for the post-job thread-leak
check.
+FROM eclipse-temurin:11-jdk-jammy
ARG SPARK_VERSION
ARG HADOOP_PROFILE
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/AbstractTestFlinkContainer.java
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/AbstractTestFlinkContainer.java
index 88e20e6dd3..95e05d4f98 100644
---
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/AbstractTestFlinkContainer.java
+++
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/AbstractTestFlinkContainer.java
@@ -77,7 +77,9 @@ public abstract class AbstractTestFlinkContainer extends
AbstractTestContainer {
"restart-strategy.fixed-delay.attempts: 2",
"restart-strategy.fixed-delay.delay: 1000");
- protected static final String DEFAULT_DOCKER_IMAGE =
"flink:1.13.6-scala_2.11";
+ // Pinned to the java11 flavour: SeaTunnel is built to Java 11 bytecode,
so a Flink image on a
+ // Java 8 runtime cannot load its classes.
+ protected static final String DEFAULT_DOCKER_IMAGE =
"flink:1.13.6-scala_2.11-java11";
private static final int FLINK_REST_PORT = 8081;
protected GenericContainer<?> jobManager;
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/Flink13Container.java
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/Flink13Container.java
index 27ebdc9e5e..d70c20cd14 100644
---
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/Flink13Container.java
+++
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/Flink13Container.java
@@ -19,6 +19,7 @@ package org.apache.seatunnel.e2e.common.container.flink;
import org.apache.seatunnel.e2e.common.container.TestContainer;
import org.apache.seatunnel.e2e.common.container.TestContainerId;
+import org.apache.seatunnel.e2e.common.util.EngineImageJdkUpgrader;
import com.google.auto.service.AutoService;
import lombok.NoArgsConstructor;
@@ -39,9 +40,14 @@ public class Flink13Container extends
AbstractTestFlinkContainer {
return TestContainerId.FLINK_1_13;
}
+ /**
+ * This tag still ships a Java 8 runtime, which cannot load the Java 11
bytecode SeaTunnel is
+ * built to, so the image is derived into a Java 11 flavour. The 1.15 to
1.18 tags already ship
+ * Java 11 and are used as published.
+ */
@Override
protected String getDockerImage() {
- return "tyrantlucifer/flink:1.13.6-scala_2.11_hadoop27";
+ return
EngineImageJdkUpgrader.toJava11("tyrantlucifer/flink:1.13.6-scala_2.11_hadoop27");
}
@Override
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/Flink14Container.java
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/Flink14Container.java
index 9d5327740e..b88014d036 100644
---
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/Flink14Container.java
+++
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/Flink14Container.java
@@ -19,6 +19,7 @@ package org.apache.seatunnel.e2e.common.container.flink;
import org.apache.seatunnel.e2e.common.container.TestContainer;
import org.apache.seatunnel.e2e.common.container.TestContainerId;
+import org.apache.seatunnel.e2e.common.util.EngineImageJdkUpgrader;
import com.google.auto.service.AutoService;
import lombok.NoArgsConstructor;
@@ -39,9 +40,12 @@ public class Flink14Container extends
AbstractTestFlinkContainer {
return TestContainerId.FLINK_1_14;
}
+ /**
+ * Java 8 tag, derived into a Java 11 flavour. See {@link
Flink13Container#getDockerImage()}.
+ */
@Override
protected String getDockerImage() {
- return "tyrantlucifer/flink:1.14.6-scala_2.11_hadoop27";
+ return
EngineImageJdkUpgrader.toJava11("tyrantlucifer/flink:1.14.6-scala_2.11_hadoop27");
}
@Override
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/Flink20Container.java
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/Flink20Container.java
index 06614e52c6..0e9b814e16 100644
---
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/Flink20Container.java
+++
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/flink/Flink20Container.java
@@ -19,6 +19,7 @@ package org.apache.seatunnel.e2e.common.container.flink;
import org.apache.seatunnel.e2e.common.container.TestContainer;
import org.apache.seatunnel.e2e.common.container.TestContainerId;
+import org.apache.seatunnel.e2e.common.util.EngineImageJdkUpgrader;
import com.google.auto.service.AutoService;
import lombok.NoArgsConstructor;
@@ -41,9 +42,13 @@ public class Flink20Container extends
AbstractTestFlinkContainer {
return TestContainerId.FLINK_1_20;
}
+ /**
+ * The 1.20 tags regressed back to a Java 8 runtime, so this image is
derived into a Java 11
+ * flavour. See {@link Flink13Container#getDockerImage()}.
+ */
@Override
protected String getDockerImage() {
- return "tyrantlucifer/flink:1.20.1-scala_2.12_hadoop27";
+ return
EngineImageJdkUpgrader.toJava11("tyrantlucifer/flink:1.20.1-scala_2.12_hadoop27");
}
@Override
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/seatunnel/ConnectorPackageServiceContainer.java
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/seatunnel/ConnectorPackageServiceContainer.java
index 9bfc96be5b..0fbbf8d721 100644
---
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/seatunnel/ConnectorPackageServiceContainer.java
+++
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/seatunnel/ConnectorPackageServiceContainer.java
@@ -53,7 +53,9 @@ import static
org.apache.seatunnel.e2e.common.util.ContainerUtil.PROJECT_ROOT_PA
@NoArgsConstructor
@Slf4j
public class ConnectorPackageServiceContainer extends AbstractTestContainer {
- private static final String JDK_DOCKER_IMAGE =
"seatunnelhub/openjdk:8u342";
+ // Keep a full JDK image, matching the JDK baseline this container ran on
before, so JVM
+ // diagnostic tools stay available to the cluster tests running inside it.
+ private static final String JDK_DOCKER_IMAGE = "eclipse-temurin:11-jdk";
private static final String CLIENT_SHELL = "seatunnel.sh";
private static final String SERVER_SHELL = "seatunnel-cluster.sh";
private GenericContainer<?> server1;
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/seatunnel/SeaTunnelContainer.java
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/seatunnel/SeaTunnelContainer.java
index b617d44c34..6a2846589e 100644
---
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/seatunnel/SeaTunnelContainer.java
+++
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/seatunnel/SeaTunnelContainer.java
@@ -92,7 +92,9 @@ public class SeaTunnelContainer extends AbstractTestContainer
implements Reusabl
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final String REST_STOP_JOB_PATH = "/stop-job";
private static final String REST_CHECKPOINT_OVERVIEW_PATH =
"/jobs/checkpoints";
- protected static final String JDK_DOCKER_IMAGE =
"seatunnelhub/openjdk:8u342";
+ // Must stay a full JDK image: ContainerUtil inspects the running server
with jps/jstack/jmap
+ // for the post-job thread-leak checks, and those tools are absent from
JRE-only images.
+ protected static final String JDK_DOCKER_IMAGE = "eclipse-temurin:11-jdk";
private static final String CLIENT_SHELL = "seatunnel.sh";
private static final String CONNECTOR_DIRECTORY =
"/tmp/seatunnel/connectors";
private static final String RUNTIME_LIBRARY_DIRECTORY =
"/tmp/seatunnel/lib";
@@ -707,7 +709,14 @@ public class SeaTunnelContainer extends
AbstractTestContainer implements Reusabl
|| s.startsWith("seatunnel-error-sink-")
// Jetty QueuedThreadPool NIO selector thread from the
embedded REST server;
// it may outlive the job and cause the E2E thread-leak check
to fail.
- || s.startsWith("qtp");
+ || s.startsWith("qtp")
+ // java.lang.ref.Cleaner's worker thread (JDK 9+ replacement
for the old
+ // sun.misc.Cleaner/finalizer based native resource cleanup).
Some JDBC drivers
+ // call Cleaner.create() to manage native buffers, and the
resulting thread runs
+ // for the life of the JVM by design, so it only shows up as a
false leak on the
+ // first job that lazily triggers it. Now that the e2e engine
container runs on a
+ // Java 11 JDK image instead of Java 8, this thread is a
normal presence.
+ || s.startsWith("Cleaner-");
}
private void classLoaderObjectCheck(Integer maxSize) throws IOException,
InterruptedException {
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/spark/Spark2Container.java
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/spark/Spark2Container.java
index 595b6b220a..5ab3dea937 100644
---
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/spark/Spark2Container.java
+++
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/spark/Spark2Container.java
@@ -19,6 +19,7 @@ package org.apache.seatunnel.e2e.common.container.spark;
import org.apache.seatunnel.e2e.common.container.TestContainer;
import org.apache.seatunnel.e2e.common.container.TestContainerId;
+import org.apache.seatunnel.e2e.common.util.EngineImageJdkUpgrader;
import com.google.auto.service.AutoService;
import lombok.NoArgsConstructor;
@@ -44,9 +45,15 @@ public class Spark2Container extends
AbstractTestSparkContainer {
return "seatunnel-spark-starter" + File.separator +
"seatunnel-spark-2-starter";
}
+ /**
+ * The published image bundles a Java 8 runtime, which cannot load the
Java 11 bytecode
+ * SeaTunnel is built to, so it is derived into a Java 11 flavour. Note
that Spark 2.4 predates
+ * Spark's own Java 11 support (SPARK-24417, released in Spark 3.0), so
this lane is expected to
+ * stay the weakest signal of the matrix.
+ */
@Override
protected String getDockerImage() {
- return "tyrantlucifer/spark:2.4.6";
+ return EngineImageJdkUpgrader.toJava11("tyrantlucifer/spark:2.4.6");
}
@Override
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/spark/Spark3Container.java
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/spark/Spark3Container.java
index fd8b3c5e47..545fd62e8f 100644
---
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/spark/Spark3Container.java
+++
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/container/spark/Spark3Container.java
@@ -19,6 +19,7 @@ package org.apache.seatunnel.e2e.common.container.spark;
import org.apache.seatunnel.e2e.common.container.TestContainer;
import org.apache.seatunnel.e2e.common.container.TestContainerId;
+import org.apache.seatunnel.e2e.common.util.EngineImageJdkUpgrader;
import com.google.auto.service.AutoService;
import lombok.NoArgsConstructor;
@@ -44,9 +45,14 @@ public class Spark3Container extends
AbstractTestSparkContainer {
return "seatunnel-spark-starter" + File.separator +
"seatunnel-spark-3-starter";
}
+ /**
+ * The published image bundles a Java 8 runtime, which cannot load the
Java 11 bytecode
+ * SeaTunnel is built to, so it is derived into a Java 11 flavour. Spark
3.3 itself supports
+ * Java 11.
+ */
@Override
protected String getDockerImage() {
- return "tyrantlucifer/spark:3.3.0";
+ return EngineImageJdkUpgrader.toJava11("tyrantlucifer/spark:3.3.0");
}
@Override
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/util/EngineImageJdkUpgrader.java
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/util/EngineImageJdkUpgrader.java
new file mode 100644
index 0000000000..9a92861711
--- /dev/null
+++
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/util/EngineImageJdkUpgrader.java
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+package org.apache.seatunnel.e2e.common.util;
+
+import org.testcontainers.images.builder.ImageFromDockerfile;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Derives Java 11 flavours of the published engine images the e2e suite pins.
+ *
+ * <p>SeaTunnel jars are compiled to Java 11 bytecode, but several of the
Flink and Spark images
+ * still ship a Java 8 runtime, so loading any SeaTunnel class inside them
fails with {@code
+ * UnsupportedClassVersionError: class file version 55.0}. No Java 11 tags are
published for those
+ * images, and falling back to the vanilla upstream images is not an option
either: the {@code
+ * *_hadoop27} Flink images carry the shaded Hadoop jars the file based
connectors need on the Flink
+ * classpath, which is exactly why they were adopted in the first place (see
issue #2291).
+ *
+ * <p>So the original image is kept byte for byte and only its JVM is
replaced: a Java 11 JDK is
+ * copied in and the image's own {@code JAVA_HOME} is re-pointed at it through
a symlink. Because
+ * the swap happens at the path the image already advertises, every hardcoded
{@code JAVA_HOME}
+ * reference and every {@code PATH} entry baked into the image keeps
resolving, which matters for
+ * the bitnami based Spark images whose startup scripts export {@code
JAVA_HOME} themselves.
+ *
+ * <p>A full JDK rather than a JRE is required because {@link ContainerUtil}
inspects running
+ * servers with {@code jps}, {@code jstack} and {@code jmap}.
+ *
+ * <p>Images that already ship Java 11 must not be routed through this class:
deriving them would
+ * cost a docker build for no benefit.
+ */
+public final class EngineImageJdkUpgrader {
+
+ /** Source of the Java 11 runtime that replaces the JVM of the derived
images. */
+ private static final String JDK_IMAGE = "eclipse-temurin:11-jdk";
+
+ /** Path {@link #JDK_IMAGE} unpacks its JDK to, and the path it is copied
from. */
+ private static final String JDK_IMAGE_JAVA_HOME = "/opt/java/openjdk";
+
+ /** Where the Java 11 JDK is installed before the image's own JAVA_HOME is
linked to it. */
+ private static final String JDK_INSTALL_PATH = "/opt/seatunnel-e2e-jdk11";
+
+ /** Prefix of the derived image names, kept stable so repeated runs reuse
the same build. */
+ private static final String DERIVED_IMAGE_PREFIX = "seatunnel-e2e-jdk11-";
+
+ /**
+ * Derived image name per source image. A docker build is expensive, so
each source image is
+ * derived at most once per JVM and the daemon keeps the result for the
rest of the job.
+ */
+ private static final Map<String, String> DERIVED_IMAGES = new
ConcurrentHashMap<>();
+
+ private EngineImageJdkUpgrader() {}
+
+ /**
+ * Returns a Java 11 flavour of {@code sourceImage}, building it on first
use.
+ *
+ * @param sourceImage published engine image that still ships a Java 8
runtime
+ * @return name of the derived image, usable anywhere the source image
name was used
+ */
+ public static String toJava11(String sourceImage) {
+ return DERIVED_IMAGES.computeIfAbsent(sourceImage,
EngineImageJdkUpgrader::build);
+ }
+
+ private static String build(String sourceImage) {
+ String dockerfile =
+ "FROM "
+ + JDK_IMAGE
+ + " AS jdk\n"
+ + "FROM "
+ + sourceImage
+ + "\n"
+ // bitnami based images build as an unprivileged user,
so take root before
+ // replacing the JDK. The e2e containers already run
as root at runtime.
+ + "USER root\n"
+ + "COPY --from=jdk "
+ + JDK_IMAGE_JAVA_HOME
+ + " "
+ + JDK_INSTALL_PATH
+ + "\n"
+ // Fail the build loudly rather than silently keeping
Java 8 if the source
+ // image does not declare JAVA_HOME. The trailing java
-version check closes
+ // a gap the JAVA_HOME test alone does not: some base
images resolve the
+ // bare
+ // `java` on PATH through /usr/bin/java ->
/etc/alternatives/java rather
+ // than
+ // through $JAVA_HOME/bin, so the symlink swap above
can succeed while the
+ // java a caller actually invokes is still the
original Java 8 one.
+ + "RUN test -n \"$JAVA_HOME\" && rm -rf \"$JAVA_HOME\"
&& ln -s "
+ + JDK_INSTALL_PATH
+ + " \"$JAVA_HOME\""
+ + " && java -version 2>&1 | grep -q 'version \"11'\n";
+ return new ImageFromDockerfile(derivedImageName(sourceImage), false)
+ .withFileFromString("Dockerfile", dockerfile)
+ .get();
+ }
+
+ /** Turns an image reference into a deterministic, docker compatible
derived image name. */
+ private static String derivedImageName(String sourceImage) {
+ return DERIVED_IMAGE_PREFIX
+ +
sourceImage.toLowerCase(Locale.ROOT).replaceAll("[^a-z0-9._-]", "-")
+ + ":latest";
+ }
+}
diff --git
a/seatunnel-e2e/seatunnel-edge-agent-e2e/src/test/java/org/apache/seatunnel/edge/agent/e2e/EdgeAgentContainer.java
b/seatunnel-e2e/seatunnel-edge-agent-e2e/src/test/java/org/apache/seatunnel/edge/agent/e2e/EdgeAgentContainer.java
index 8958df7295..d5792e4dd1 100644
---
a/seatunnel-e2e/seatunnel-edge-agent-e2e/src/test/java/org/apache/seatunnel/edge/agent/e2e/EdgeAgentContainer.java
+++
b/seatunnel-e2e/seatunnel-edge-agent-e2e/src/test/java/org/apache/seatunnel/edge/agent/e2e/EdgeAgentContainer.java
@@ -34,7 +34,7 @@ import java.util.stream.Stream;
public class EdgeAgentContainer extends GenericContainer<EdgeAgentContainer> {
private static final String AGENT_LOGGER_NAME = "edge-agent-e2e";
- private static final String JDK_IMAGE = "seatunnelhub/openjdk:8u342";
+ private static final String JDK_IMAGE = "eclipse-temurin:11-jre";
private static final String AGENT_HOME = "/opt/edge-agent";
private static final String APP_LOG_FILE = AGENT_HOME +
"/log/edge-agent.log";
private static final String STARTUP_LOG_FILE = AGENT_HOME +
"/edge-agent.out";
diff --git
a/seatunnel-e2e/seatunnel-engine-e2e/seatunnel-engine-k8s-e2e/src/test/resources/seatunnel_dockerfile
b/seatunnel-e2e/seatunnel-engine-e2e/seatunnel-engine-k8s-e2e/src/test/resources/seatunnel_dockerfile
index 4acbb9a821..976331f5e9 100644
---
a/seatunnel-e2e/seatunnel-engine-e2e/seatunnel-engine-k8s-e2e/src/test/resources/seatunnel_dockerfile
+++
b/seatunnel-e2e/seatunnel-engine-e2e/seatunnel-engine-k8s-e2e/src/test/resources/seatunnel_dockerfile
@@ -15,7 +15,9 @@
# limitations under the License.
#
-FROM openjdk:8u162-jdk
+# The build now targets Java 11 bytecode, so the pod JVM must be at least Java
11.
+# A full JDK is kept because the engine e2e helpers inspect the running server
with jps/jstack.
+FROM eclipse-temurin:11-jdk
ENV SEATUNNEL_HOME="/opt/seatunnel"
COPY /jars/seatunnel-shade-hadoop3-uber.jar
${SEATUNNEL_HOME}/lib/seatunnel-shade-hadoop3-uber.jar
COPY /jars/seatunnel-transforms-v2.jar
${SEATUNNEL_HOME}/lib/seatunnel-transforms-v2.jar
diff --git a/seatunnel-examples/seatunnel-flink-examples/pom.xml
b/seatunnel-examples/seatunnel-flink-examples/pom.xml
index a39d6d1437..79098ddb40 100644
--- a/seatunnel-examples/seatunnel-flink-examples/pom.xml
+++ b/seatunnel-examples/seatunnel-flink-examples/pom.xml
@@ -36,6 +36,7 @@
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
+ <maven.compiler.release>8</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
diff --git
a/seatunnel-examples/seatunnel-flink-examples/seatunnel-flink-13-example/pom.xml
b/seatunnel-examples/seatunnel-flink-examples/seatunnel-flink-13-example/pom.xml
index ca17fd3ea3..b56ff337f2 100644
---
a/seatunnel-examples/seatunnel-flink-examples/seatunnel-flink-13-example/pom.xml
+++
b/seatunnel-examples/seatunnel-flink-examples/seatunnel-flink-13-example/pom.xml
@@ -31,6 +31,7 @@
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
+ <maven.compiler.release>8</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
diff --git
a/seatunnel-examples/seatunnel-flink-examples/seatunnel-flink-15-example/pom.xml
b/seatunnel-examples/seatunnel-flink-examples/seatunnel-flink-15-example/pom.xml
index e861d6fc99..8cfdce8a03 100644
---
a/seatunnel-examples/seatunnel-flink-examples/seatunnel-flink-15-example/pom.xml
+++
b/seatunnel-examples/seatunnel-flink-examples/seatunnel-flink-15-example/pom.xml
@@ -30,6 +30,7 @@
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
+ <maven.compiler.release>8</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
diff --git
a/seatunnel-examples/seatunnel-flink-examples/seatunnel-flink-20-example/pom.xml
b/seatunnel-examples/seatunnel-flink-examples/seatunnel-flink-20-example/pom.xml
index 82c53c05a6..5fc166f3a6 100644
---
a/seatunnel-examples/seatunnel-flink-examples/seatunnel-flink-20-example/pom.xml
+++
b/seatunnel-examples/seatunnel-flink-examples/seatunnel-flink-20-example/pom.xml
@@ -30,6 +30,7 @@
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
+ <maven.compiler.release>8</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
diff --git a/seatunnel-formats/seatunnel-format-protobuf/pom.xml
b/seatunnel-formats/seatunnel-format-protobuf/pom.xml
index 8f8f7030f6..d36e9d3a4b 100644
--- a/seatunnel-formats/seatunnel-format-protobuf/pom.xml
+++ b/seatunnel-formats/seatunnel-format-protobuf/pom.xml
@@ -28,6 +28,7 @@
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
+ <maven.compiler.release>8</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<protobuf.version>3.25.3</protobuf.version>
<protoc.jar.version>3.11.4</protoc.jar.version>
diff --git a/tools/update_modules_check/test_ci_scope.py
b/tools/update_modules_check/test_ci_scope.py
index 437bc194a9..42c6a0a0d8 100644
--- a/tools/update_modules_check/test_ci_scope.py
+++ b/tools/update_modules_check/test_ci_scope.py
@@ -81,7 +81,6 @@ class CiScopeTest(unittest.TestCase):
["tools/benchmarks/save_jmh_result.py"],
)
)
-
def test_skip_full_api_check_for_dist_only_fork_change(self) -> None:
self.assertFalse(
should_run_full_api_check(