Skip to content

Upgrade to Gradle 9.3.1 with JDK 21 build requirement#365

Open
jbachorik wants to merge 23 commits intomainfrom
jb/gradle_9
Open

Upgrade to Gradle 9.3.1 with JDK 21 build requirement#365
jbachorik wants to merge 23 commits intomainfrom
jb/gradle_9

Conversation

@jbachorik
Copy link
Collaborator

@jbachorik jbachorik commented Feb 11, 2026

What does this PR do?:

Upgrades the build system from Gradle 8.12 to Gradle 9.3.1 and updates the build JDK requirement from JDK 11 to JDK 21. Also adds Dependabot configuration for automated dependency updates.

Key changes:

  • Gradle 8.12 → 9.3.1
  • Spotless plugin 6.x → 7.0.2
  • JMH plugin 0.7.2 → 0.7.3
  • CI and Docker builds now use JDK 21 (Gradle 9 requires JDK 17+)
  • Fix Kotlin 2.2 API changes (capitalize, createTempFile, exec)
  • Fix Spotless 7.x API changes (editorConfigOverride, leadingTabsToSpaces)
  • Two-JDK pattern: build with JDK 21, test with configurable JDK
  • Migrate Test/JavaExec tasks to Exec tasks to bypass Gradle 9 toolchain compatibility issues on musl systems
  • Fix Exec task JDK resolution: defer executable lookup to execution time so JAVA_TEST_HOME is read correctly
  • Fix Exec task environment: explicitly pass through CI environment variables (LIBC, TEST_COMMIT, etc.)
  • Test filtering now uses -Ptests property instead of --tests flag (Exec tasks don't support --tests)
  • Add Dependabot for Gradle and GitHub Actions dependency updates

Motivation:

Gradle 9 brings performance improvements, better dependency management, and is required for long-term support. JDK 21 is the current LTS and provides the best tooling support while still allowing --release 8 targeting.

Additional Notes:

  • The compiled bytecode still targets Java 8 runtime (unchanged)
  • JDK 21+ emits deprecation warnings for --release 8; suppressed with -Xlint:-options
  • Build JDK configuration documented in AGENTS.md for future reference
  • Config-specific test tasks (testdebug, testrelease) use Exec task type to bypass Gradle's toolchain system, which has musl compatibility issues
  • Exec tasks differ from Test tasks: executable and environment must be resolved at execution time, not configuration time
  • Dependabot will create weekly PRs for Gradle and GitHub Actions updates

How to test the change?:

  1. Run gradle build - should complete successfully
  2. Run gradle spotlessCheck - formatting checks pass
  3. Run gradle test with -Ptests filter - test filtering works
  4. Run with JAVA_TEST_HOME set - multi-JDK testing works
  5. Run utils/run-docker-tests.sh --libc=musl --jdk=21 - Docker tests work on musl (Alpine)
  6. CI pipeline should pass with correct JDK versions for each test matrix combination

For Datadog employees:

  • If this PR touches code that signs or publishes builds or packages, or handles
    credentials of any kind, I've requested a review from @DataDog/security-design-and-guidance.
  • This PR doesn't touch any of that.
  • JIRA: [JIRA-XXXX]

Unsure? Have a question? Request a review!

🤖 Generated with Claude Code

@jbachorik jbachorik added the AI label Feb 11, 2026
@dd-octo-sts
Copy link

dd-octo-sts bot commented Feb 11, 2026

CI Test Results

Run: #22042302200 | Commit: a04f944 | Duration: 9m 47s (longest job)

All 40 test jobs passed

Status Overview

JDK glibc-aarch64/debug glibc-amd64/debug musl-aarch64/debug musl-amd64/debug
8 - - -
8-ibm - - -
8-j9 - -
8-librca - -
8-orcl - - -
8-zing - -
11 - - -
11-j9 - -
11-librca - -
11-zing - -
17 - -
17-graal - -
17-j9 - -
17-librca - -
17-zing - -
21 - -
21-graal - -
21-librca - -
21-zing - -
25 - -
25-graal - -
25-librca - -

Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled

Summary: Total: 40 | Passed: 40 | Failed: 0


Updated: 2026-02-15 20:25:04 UTC

@dd-octo-sts
Copy link

dd-octo-sts bot commented Feb 11, 2026

Scan-Build Report

User:runner@runnervmjduv7
Working Directory:/home/runner/work/java-profiler/java-profiler/ddprof-lib/src/test/make
Command Line:make -j4 all
Clang Version:Ubuntu clang version 18.1.3 (1ubuntu1)
Date:Sun Feb 15 20:14:29 2026

Bug Summary

Bug TypeQuantityDisplay?
All Bugs1
Unused code
Dead assignment1

Reports

Bug Group Bug Type ▾ File Function/Method Line Path Length
Unused codeDead assignmentlibraryPatcher_linux.cpppatch_library_unlocked941

@jbachorik jbachorik force-pushed the jb/gradle_9 branch 2 times, most recently from 90d13d7 to 0970a33 Compare February 11, 2026 15:42
@pr-commenter
Copy link

pr-commenter bot commented Feb 11, 2026

Integration Tests

All 30 integration tests passed

📊 Dashboard · 👷 Pipeline · 📦 e553f15d

@jbachorik jbachorik force-pushed the jb/gradle_9 branch 2 times, most recently from 400823d to a33b077 Compare February 13, 2026 07:51
jbachorik and others added 18 commits February 13, 2026 13:34
- Gradle 8.12 → 9.3.1, Spotless 7.0.2, JMH 0.7.3
- CI and Docker builds now use JDK 21 (Gradle 9 requires JDK 17+)
- Fix Kotlin 2 API changes (capitalize, createTempFile, exec)
- Fix Spotless 7.x API changes (editorConfigOverride, leadingTabsToSpaces)
- Two-JDK pattern: build JDK 21, test JDK configurable

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Set explicit executable for runUnwindingValidator and unwindingReport
tasks to avoid Gradle 9 javaLauncher toolchain probing failures.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Gradle 9 detects that compileJava9Java uses mainSourceSet.output
which includes copyExternalLibs destination. Add explicit dependency.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix PATH env variable escaping in Dockerfile heredocs
- Add coreutils to Alpine base image for chmod

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 'assembled' publication with all build artifacts
- Include POM metadata (license, SCM, developers)
- Configure signing with in-memory PGP keys
- Add publication assertions for CI requirements

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add javaLauncher workaround for Test tasks (musl compatibility)
- Fix configurations to be resolvable-only (Gradle 9 requirement)
- Upgrade plugins: ben-manes.versions 0.51.0, download 5.6.0
- Use lazy configuration for Javadoc tasks
- Fix eager task resolution in publishing assertions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Use lazy task resolution for javadocJar (map instead of get)
- Use task matching for assembleReleaseJar (registered in afterEvaluate)
- Extract javaLauncher workaround to documented helper methods

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace Test/JavaExec tasks with Exec tasks to bypass Gradle's
toolchain system. Adds JUnit Platform Console Launcher dependency.

- Same task names on all platforms (testdebug, testrelease)
- JAVA_TEST_HOME support everywhere for multi-JDK testing
- No platform-specific code paths
- Verified working in musl containers

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Preserve build-script args in doFirst blocks (LIFO order)
- Fix test filter to only use --select-method for '#' separator
- Update javadoc to reference Exec tasks instead of Test/JavaExec
- Simplify build.gradle.kts to use doFirst (plugin preserves args)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Move test properties into plugin (avoid doFirst ordering issues)
- Fix test filter: use --select-class instead of --scan-classpath when filtering
- Simplify build.gradle.kts (plugin now handles all properties)
- Tests now execute successfully with -Ptests filter

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Two critical fixes for Exec-based test tasks:

1. Defer executable resolution to execution time
   - Move testJavaExecutable() call from configuration to doFirst
   - CI sets JAVA_TEST_HOME at runtime, not visible at config time
   - Fixes JDK version mismatch (tests ran with build JDK not test JDK)

2. Explicitly pass through CI environment variables
   - Exec tasks don't inherit environment like Test tasks
   - Add LIBC, KEEP_JFRS, TEST_COMMIT, TEST_CONFIGURATION, SANITIZER
   - Fixes assumption failures in MuslDetectionTest and others

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Uses Test tasks on glibc/macOS, Test-with-Exec-delegation on musl.
Provides unified --tests flag interface on all platforms.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add dependency on :ddprof-test-native:linkLib for Test tasks.
Previously only Exec tasks had this dependency, causing
RemoteSymbolicationTest to fail with NoClassDefFoundError when
RemoteSymHelper's static initializer couldn't load libddproftest.so.

The fix changes from type-based matching (Exec only) to name-based
matching (all tasks starting with "test"), ensuring both Test and
Exec tasks wait for the native library to be built.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove the dual Test+Exec task approach for musl in favor of direct
Exec task creation. The Test task wrapper was causing Gradle internal
errors ("NoSuchMethodError: getMainType") during configuration.

Changes:
- Create Exec tasks directly for musl (no Test task wrapper)
- Read test filters from -Ptests project property instead of --tests flag
- Remove testdebugExec hidden task, use testdebug directly

Known Issue:
- musl + Liberica JDK 11 still fails with NoSuchMethodError when
  running JUnit Console Launcher. This appears to be a pre-existing
  issue with that specific JDK build. JDK 21 on musl works fine.

Tested:
- ✅ JDK 11 glibc: 144 tests run (Test task)
- ✅ JDK 21 musl: Tests run (Exec task)
- ❌ JDK 11 musl: NoSuchMethodError (JDK build issue)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements platform-conditional test execution to support both glibc/macOS
and musl environments with a unified -Ptests interface.

Changes:
- Add ProfilerTestRunner with JUnit Platform Launcher API
- Create Test tasks on glibc/macOS, Exec tasks on musl
- Fix JDK 11 + musl by removing LD_LIBRARY_PATH (prevents cross-JDK library loading)
- Support both . and # method separators with proper heuristic
- Update all docs to use -Ptests syntax consistently
- Add warning when --tests flag used on Test tasks
- Switch from junit-platform-console to junit-platform-launcher
- Add build-logic to Dependabot monitoring
- Improve error handling in javadocJar task

Verified on musl + JDK 11, musl + JDK 21, and macOS.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
jbachorik and others added 2 commits February 13, 2026 13:45
Restore original camelCase naming convention for test tasks to maintain
compatibility with existing workflows. Gradle task resolution is
case-insensitive, so both `./gradlew testDebug` and `./gradlew testdebug`
work, but camelCase is the standard Gradle convention.

Changes:
- ProfilerTestPlugin.kt: Capitalize first letter of config name when
  creating tasks (testDebug, testRelease, testAsan, testTsan)
- run-docker-tests.sh: Restore CONFIG_CAPITALIZED logic
- Update all documentation to use camelCase task names

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Clean up excessive debug logging that outputs on every task configuration.
The info about executable and classpath size was not particularly actionable
and added noise to build output.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
jbachorik and others added 2 commits February 13, 2026 13:55
Address code quality review comment: the 'args' parameter in runTests()
was never used. All configuration is read from system properties via
System.getProperty("test.filter"), making the parameter unnecessary.

Changes:
- Remove String[] args parameter from runTests() method
- Update call site in main() to invoke runTests() without arguments
- Apply Spotless formatting to ddprof-lib/build.gradle.kts

Resolves GitHub Code Quality bot review comment on PR #365.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Apply the same LD_LIBRARY_PATH removal fix to runUnwindingValidator
and unwindingReport tasks that was previously applied to test tasks.

Without this fix, JDK 11 + musl systems fail with cross-JDK library
conflicts when LD_LIBRARY_PATH causes the launcher to load the wrong
libjli.so library. Removing LD_LIBRARY_PATH allows RPATH to work
correctly and load the correct library from $ORIGIN/../lib/jli.

Tasks fixed:
- runUnwindingValidator{Config} (Exec tasks)
- unwindingReport{Config} (Exec tasks)

Resolves unwinding report failures on musl CI builds.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@jbachorik jbachorik marked this pull request as ready for review February 13, 2026 14:04
@jbachorik jbachorik requested a review from a team as a code owner February 13, 2026 14:04
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant