Skip to content

chore(build): Switch to JDK 21 and upgrade Mockito, Robolectric and Error Prone - #6242

Draft
markushi wants to merge 2 commits into
mainfrom
build/jdk-21
Draft

markushi wants to merge 2 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, so that we can run Robolectric tests on SDK 37 (Android 17). The bytecode we publish does not change: libraries still target Java 8 (Spring Boot 4 / Spring 7 modules still 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 runs on a JDK older than 21.
  • 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.

Robolectric 4.15 → 4.17

  • 4.17 is the first version that supports SDK 37. SDK 37 needs Java 21.
  • 4.16 removed SDK 21/22, so sentry-android-core now runs its default sandbox on SDK 23.
  • Android unit tests get --add-opens=java.base/java.io. Without it, the SDK 37 sandbox (the default, as targetSdk is 37) cannot start.

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 Java 21, the build JDK.
  • 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.
  • 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.

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.

💡 Motivation and Context

Preparation for SDK 37 support (for example ActivityManager.registerAnrWarningListener). We cannot test it with Robolectric on JDK 17.

💚 How did you test it?

  • ran 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

#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.60.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
Comment on lines 17 to 24
final class ApplicationNotResponding extends RuntimeException {
private static final long serialVersionUID = 252541144579117016L;

// Never serialized.
@SuppressWarnings("serial")
private final @Nullable Thread thread;

ApplicationNotResponding(final @Nullable String message) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Missing copyright and license name in vendored file header

io.sentry.android.core.ApplicationNotResponding — Header has source URL and "Based on" origin but omits the required Copyright line and License name (present on sibling ANRWatchDog.java). Add Copyright (c) 2016 Salomon BRYS and The MIT License (or equivalent) to the file header.

Evidence
  • Lines 1–2 state source URL SalomonBrys/ANR-WatchDog/.../ANRError.java and "Based on the class above" (vendored).
  • Header has no Copyright line and no license name (MIT / Licensed under).
  • ANRWatchDog.java in the same package includes Adapted-from, MIT License, and Copyright (c) 2016 Salomon BRYS.
  • THIRD_PARTY_NOTICES.md lists Copyright (c) 2016 Salomon BRYS and MIT for this library.

Identified by Warden · check-code-attribution · 4MB-UVC

Comment on lines 17 to 24
final class ApplicationNotResponding extends RuntimeException {
private static final long serialVersionUID = 252541144579117016L;

// Never serialized.
@SuppressWarnings("serial")
private final @Nullable Thread thread;

ApplicationNotResponding(final @Nullable String message) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Vendored class missing from THIRD_PARTY_NOTICES.md Scope

io.sentry.android.core.ApplicationNotResponding — Adapted from ANR-WatchDog ANRError.java, but the SalomonBrys ANR-WatchDog entry Scope only names io.sentry.android.core.ANRWatchDog. Add ApplicationNotResponding to that entry's Scope.

Evidence
  • File header cites ANRError.java from SalomonBrys ANR-WatchDog commit 1969075.
  • THIRD_PARTY_NOTICES.md "SalomonBrys — ANR-WatchDog (MIT)" Scope only states code resides in io.sentry.android.core.ANRWatchDog.
  • Search of THIRD_PARTY_NOTICES.md finds no ApplicationNotResponding or ANRError Scope reference.
  • Class remains in tree and is used by ANRWatchDog / AnrIntegration.

Identified by Warden · check-code-attribution · DUA-PUT

This branch has not been deployed

No deployments
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.

1 participant