Skip to content

chore(build): Compile with a JDK 21 toolchain and upgrade Mockito and Error Prone - #6242

Merged
markushi merged 32 commits into
mainfrom
build/jdk-21
Oct 21, 2026
Merged

markushi merged 32 commits into
mainfrom
build/jdk-21

Conversation

@markushi

@markushi markushi commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

📜 Description

Switches the build and CI from JDK 17 to JDK 21, and upgrades the tools that the new JDK forces us to move: Mockito, Error Prone and NullAway. Compilation and tests run on a JDK 21 toolchain. The bytecode we publish still targets Java 8 (Spring Boot 4 / Spring 7 modules target 17).

Just changing to 21 has a few ripple effects, so there's quite a broad set of changes involved across the codebase.

JDK 21

  • All CI workflows now use JDK 21. CONTRIBUTING.md is updated.
  • The build fails fast with a clear message when Gradle requires a JDK older than 21.
  • A JDK 21 toolchain in the new io.sentry.jvm-targets convention plugin (build-logic) compiles the code and runs the tests, so a contributor on a newer JDK gets the same output as CI. The foojay resolver fetches a JDK 21 when no local one matches.
  • JVM library modules now compile with --release <target>. A newer JDK could otherwise let APIs such as List.getFirst() get into Java 8 bytecode without a compile error, reducing the risk of introducing breaking changes for Android.
  • The Java 8 and Java 17 pins apply to main compilation only, so test code - which is never published - simply follows the toolchain instead of being patched back up per task.

Mockito 4.8 → 5.24, mockito-kotlin 4.1 → 6.4

  • Mockito 4.8 cannot mock on JDK 21 unless we set net.bytebuddy.experimental.
  • mockito-inline is replaced with mockito-core. Mockito 5 uses the inline mock maker by default.
  • Mockito 5 and mockito-kotlin 5+ are built for Java 11. Thus test code (never published) now compiles for the toolchain's Java 21 rather than main's Java 8.
  • 6 tests use anyVararg(), because in Mockito 5 any() on a varargs parameter matches exactly one argument.

Error Prone 2.11 → 2.50, NullAway 0.9.5 → 0.14.2, Gradle plugin 3.0.1 → 5.1.1

  • The old versions crash on JDK 21: Error Prone 2.11 fails with NoSuchMethodError: TreeMaker.Select, and NullAway 0.9.5 cannot load against a newer Error Prone. Neither bump can be split out of this PR.
  • The new NullAway found 15 errors, fixed here:
    • Scope.executeBeforeBreadcrumb could throw an NPE. This happens when the callback returns null and the close() of the reentrancy guard then throws.
    • Spring 7 is annotated with JSpecify. Our Spring 7 advices dereferenced MethodInvocation.getThis(), which is null for static methods. They now pass a null target class to AopUtils.getMostSpecificMethod. invoke() is now @Nullable, the same as the Spring 7 contract.
    • SentryAppender (logback) passes an empty array instead of null varargs. The behavior is the same.
  • The new Error Prone version and the JDK 21 javac lints gave 114 new warnings:
    • Simple ones are fixed: pattern-matching instanceof (Java 17 modules only), Locale.ROOT for toUpperCase, explicit long → double casts, /** on non-Javadoc comments, and modifiers on effectively-private members.
    • The others are suppressed in the code, each with a one-line reason: identity comparisons with sentinels, rrweb enum ordinals, JdkObsolete replacements that need Java 10+, this-escape in public non-final classes, serial, and the vendored Gson.

Samples

  • The samples follow the toolchain too, with one exception: the five modules the Spring Boot 2.x matrix builds keep their published Java level (11, and 8 for sentry-samples-spring), as otherwise those would stop working because of Unsupported class file major version 65 errors.

Other

  • SentryEnvelopeItemTest."fromAttachment with file SecurityManager denies read access" installs a SecurityManager. Since JDK 18 this needs -Djava.security.manager=allow, which the sentry tests now set.
  • The Build job name no longer carries a Java version that goes stale at the next bump.

💡 Motivation and Context

Preparation for SDK 37 support (for example ActivityManager.registerAnrWarningListener). Robolectric 4.17 is the first version that supports SDK 37, and SDK 37 needs Java 21, so JDK 21 has to land first.

💚 How did you test it?

Tests

📝 Checklist

  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

  • Robolectric 4.15 → 4.17 with the SDK 37 sandbox, including the 13 re-rendered snapshots
  • Scope the Java pins of the five samples outside the system tests (sentry-samples-android, -ktor-client, -openfeign, -servlet, -netflix-dgs) to main compilation, so every sample treats its test code the same way
  • Fix the flaky InternalSentrySdkTest, which reads session.json right after an asynchronous write

#skip-changelog

@sentry

sentry Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.61.0 (1) release

⚙️ sentry-android Build Distribution Settings

@markushi markushi changed the title build: Switch to JDK 21 and upgrade Mockito, Robolectric and Error Prone chore(build): Switch to JDK 21 and upgrade Mockito, Robolectric and Error Prone Oct 9, 2026

@runningcode runningcode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm all for this! i gave it a first round of reviews, ping me for another round!

Comment thread buildSrc/build.gradle.kts
Comment thread gradle/libs.versions.toml
Comment thread gradle/libs.versions.toml
Comment thread sentry-system-test-support/build.gradle.kts Outdated
Comment thread build.gradle.kts Outdated
Comment thread build.gradle.kts Outdated
Comment thread build.gradle.kts Outdated
Comment thread build.gradle.kts
Comment thread sentry/src/main/java/io/sentry/SynchronizedCollection.java
@markushi markushi changed the title chore(build): Switch to JDK 21 and upgrade Mockito, Robolectric and Error Prone chore(build): Compile with a JDK 21 toolchain and upgrade Mockito and Error Prone Oct 13, 2026
@markushi
markushi marked this pull request as ready for review October 14, 2026 07:40
Comment thread build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts Outdated

@runningcode runningcode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gave it another round of review! it looks much better!

Comment thread build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts Outdated
Comment thread build-logic/build.gradle.kts Outdated
Comment thread gradle/libs.versions.toml
Comment thread settings.gradle.kts Outdated
Comment thread build.gradle.kts Outdated
Comment thread sentry-test-support/build.gradle.kts Outdated
Comment thread sentry-system-test-support/build.gradle.kts Outdated
Comment thread sentry-spring/build.gradle.kts
Comment thread sentry-spring-jakarta/build.gradle.kts
Comment thread sentry-apollo-3/build.gradle.kts

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread build-logic/src/main/kotlin/io/sentry/gradle/JdkTargetConvention.kt

@runningcode runningcode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right toolchains don't solve this problem at all. i feel adding it only makes this more complicated.

Comment thread build-logic/src/main/kotlin/io/sentry/gradle/JdkTargetConvention.kt
Comment thread build-logic/src/main/kotlin/io/sentry/gradle/JdkTargetConvention.kt
Comment thread build-logic/src/main/kotlin/io/sentry/gradle/SentryCompilationPlugin.kt Outdated
Comment thread build-logic/src/main/kotlin/io/sentry/gradle/SentryCompilationPlugin.kt Outdated
Comment thread build-logic/src/main/kotlin/io/sentry/gradle/JdkTargetConvention.kt
Comment thread build-logic/build.gradle.kts Outdated
Comment thread build.gradle.kts Outdated
Comment thread build-logic/src/main/kotlin/io/sentry/gradle/JdkTargetConvention.kt

@runningcode runningcode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i left a comment. separately looks like updating the SDK is leading to a real build error here about serializing the thread field inside ApplicationNotResponding. seems like something we should definitly fix (and its great that bumping the JDK fixes it)

@runningcode runningcode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approved! let's do the rest in follow ups!

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 374ff7d. Configure here.

Comment thread build-logic/src/main/kotlin/io/sentry/gradle/JdkTargetConvention.kt
@sentry-junior

sentry-junior Bot commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

🐑 PR Shepherd — head 374ff7d4c00bbd82dfb07896aa8311bdfc94c60b

Check Class Diagnosis
Build and Analyze SDK Size flaky Size upload (uploadSentryBundleRelease) got a 502 Bad Gateway from Sentry; the build itself succeeded. Unrelated to the diff.

Actions

  • Re-ran failed jobs of SDK Size Analysis run (attempt 2). This is the only retry for this check on this SHA.

@markushi
markushi merged commit 5e493bd into main Oct 21, 2026
70 of 71 checks passed
@markushi
markushi deleted the build/jdk-21 branch October 21, 2026 09:56
@sentry-junior sentry-junior Bot mentioned this pull request Oct 21, 2026
runningcode added a commit that referenced this pull request Oct 21, 2026
* chore: update scripts/update-sentry-native-ndk.sh to 0.17.4 (#6278)

Co-authored-by: GitHub <[email protected]>

* feat(android): Add masked screenshot capture for Hybrid SDKs (#6281)

* feat(android): Add masked screenshot capture for Hybrid SDKs

Hybrid SDKs capture screenshots for their own errors through
ScreenshotUtils.takeScreenshot, which ignores the screenshot masking
options. Add ScreenshotUtils.takeMaskedScreenshot, backed by a shared
captureMaskedScreenshot that ScreenshotEventProcessor now uses as well,
so native and hybrid screenshots follow the same masking rules.

Refs getsentry/sentry-react-native#6900

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* changelog

* ref(android): Narrow catches in ScreenshotMasking

Catch only InterruptedException around the main-thread wait and
RuntimeException around bitmap masking. Keep the broad catch for view
hierarchy traversal, which runs custom View code, but let fatal errors
through with ExceptionUtils.rethrowIfFatal.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* changelog: Move entry to Internal

* ref(android): Move replay availability check to ScreenshotMasking

Add ScreenshotMasking.isAvailable() so the replay integration class name
no longer needs to be public on SentryAndroid.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>

* ci: Move jobs from Bitrise back to GitHub-hosted runners (#6289)

Co-Authored-By: Nelson Osacky <[email protected]>

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>

* chore(deps): bump the github-actions group across 1 directory with 4 updates (#6280)

Bumps the github-actions group with 4 updates in the / directory: [actions/setup-java](https://github.com/actions/setup-java), [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [getsentry/craft](https://github.com/getsentry/craft).


Updates `actions/setup-java` from 6.0.1 to 6.1.0
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](actions/setup-java@de7274f...b843ebf)

Updates `github/codeql-action/init` from 4.38.3 to 4.39.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@24c5418...6f2ac81)

Updates `github/codeql-action/analyze` from 4.38.3 to 4.39.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@24c5418...6f2ac81)

Updates `getsentry/craft` from 2.34.1 to 2.35.0
- [Release notes](https://github.com/getsentry/craft/releases)
- [Changelog](https://github.com/getsentry/craft/blob/master/CHANGELOG.md)
- [Commits](getsentry/craft@3f2abdc...7a78575)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: getsentry/craft
  dependency-version: 2.35.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: github/codeql-action/init
  dependency-version: 4.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* docs: Require issue discussion before PRs (#6288)

* docs: Require issue discussion before PRs
Co-Authored-By: Chris Aigner <[email protected]>

* docs: Add Sentry logo header to CONTRIBUTING.md
Co-Authored-By: Chris Aigner <[email protected]>

* Apply suggestion from @christophaigner

* Apply suggestion from @christophaigner

---------

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: Chris Aigner <[email protected]>

* fix(client-reports): Count spans in batched span envelope items (#6265)

Prior to this commit, ClientReportRecorder didn't have any explicit logic for dealing with span envelopes because sentry-java didn't implement them. That meant that any span envelopes created by hybrid SDKs and dropped by sentry-java would be shunted to the recorder's fallback branch and wrongly register a single dropped span per dropped envelope, rather than the actual number.

This commit adds the missing span envelope logic, so that we now report the actual span count.

Refs [sentry-docs#19854](getsentry/sentry-docs#19854)

* build(deps): Bump certifi to 2026.10.19 (#6333)

Removes trust in the compromised eMudhra/emSign CA roots (VULN-3216).

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: Geoff Goldsmith <[email protected]>

* test: Add an in-process MockSentryServer to sentry-test-support (#6266)

First step of moving the sample system tests into the modules they
cover. The server stands in for the Python mock server: it binds a free
port, accepts envelopes through the SDK's real HTTP transport, and lets
tests wait for a matching one.

The release-minified UI test APK pulls in sentry-test-support, so R8
needs to be told the JDK-only com.sun.net.httpserver classes are absent.

Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>

* ci: Use the latest Python 3.10 patch in CI (#6339)

ubuntu-latest now resolves to Ubuntu 26.04, and actions/python-versions
ships no 3.10.5 build for it, so "Set up Python" fails before any test
runs in the Spring Boot matrix and system-test jobs. Pinning the minor
version lets setup-python pick the newest 3.10.x available for the
runner image while keeping requirements.txt and the system-test runner
on the same Python minor.

Co-authored-by: Claude Opus 5.5 <[email protected]>

* chore(build): Compile with a JDK 21 toolchain and upgrade Mockito and Error Prone (#6242)

* build: Switch to JDK 21 and upgrade Mockito, Robolectric and Error Prone

* build: Compile tests for JDK 21 and fix buildSrc JVM target

* build: Compile with a JDK 21 toolchain from a build-logic convention plugin

* docs(kafka): Explain the explicit double cast at the latency call site

* build: Compile the samples and their tests with the toolchain JDK

* Format code

* build: Drop the now-unused JvmTarget imports from the samples

* build: Clarify the jvm-targets plugin comments and rename its helper

* build: Require JDK 21 to run Gradle again

* build: Keep the Spring Boot 2 sample apps on their published bytecode level

* ci: Drop the stale Java version from the build job name

* build: Keep Robolectric at 4.15 and leave its test environment untouched

* build: Move the Java 8 release pin into the jvm-targets convention plugin

* build: Drop the Error Prone and NullAway code fixes, they move to their own PR

* ci: Drop the stale Java version from the build job name

* fix(core): Suppress the new Error Prone and javac 21 findings in the sentry module

* fix(core): Resolve the remaining Error Prone and javac 21 findings in the sentry module

* build: Move the JDK and bytecode level decisions into the io.sentry.compilation plugin

* Address PR comments

* test(android): Make the flush timeout verifies match the real log call

* chore(core): Reword the JDK 21 suppression comments

* build: Keep only the javac unit test targets inside afterEvaluate

* build: Drop afterEvaluate, pin the Kotlin API level and rename the convention plugin

* Fix JDK 21 findings in sentry-android-core (#6261)

Fix JDK 21 findings in sentry-android-core

* Fix JDK 21 findings in the Spring modules (#6260)

* Fix JDK 21 findings in the JVM integrations (#6259)

* fix multiplatform target compilations

---------

Co-authored-by: Sentry Github Bot <[email protected]>

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub <[email protected]>
Co-authored-by: Antonis Lilis <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Chris Aigner <[email protected]>
Co-authored-by: Adam Brown <[email protected]>
Co-authored-by: Geoff Goldsmith <[email protected]>
Co-authored-by: Nelson Osacky <[email protected]>
Co-authored-by: Markus Hintersteiner <[email protected]>
Co-authored-by: Sentry Github Bot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants