Skip to content

build: Add Java 8 API compatibility checks#5745

Open
adinauer wants to merge 5 commits into
mainfrom
ci/java8-api-compatibility
Open

build: Add Java 8 API compatibility checks#5745
adinauer wants to merge 5 commits into
mainfrom
ci/java8-api-compatibility

Conversation

@adinauer

@adinauer adinauer commented Jul 8, 2026

Copy link
Copy Markdown
Member

📜 Description

Add Java 8 runtime API compatibility coverage to JVM SDK modules using Animal Sniffer and the Codehaus Java 8 signature.

This applies ru.vyarus.animalsniffer to Java 8 java-library SDK modules that were missing it and adds:

org.codehaus.mojo.signature:java18:1.0@signature

to those modules, with the signature version defined in gradle/libs.versions.toml as java18Signature. Modules that already used Animal Sniffer keep their existing gummy-bears signature and also get the Codehaus Java 8 signature. The plugin checks signatures independently, so the Java 8 check still catches plain JVM incompatibilities while the existing Android/desugaring coverage remains intact.

💡 Motivation and Context

We recently hit a Java 8 runtime incompatibility from a method reference that compiled on a newer JDK but is unavailable on Java 8. Targeting Java 8 bytecode is not sufficient to catch this class of issue, so published JVM SDK modules should also be checked against the Java 8 runtime API surface.

This now runs through the existing check lifecycle and therefore through the existing Build workflow on PRs and main.

Refs GH-5741

💚 How did you test it?

./gradlew spotlessApply apiDump
BUILD SUCCESSFUL
./gradlew check --no-configuration-cache -Dorg.gradle.configureondemand=false
BUILD SUCCESSFUL

The check run includes Android modules and passed, confirming the duplicated JVM Animal Sniffer configuration does not break Android builds.

A stacked validation PR intentionally introduces newer JDK API references in multiple JVM modules to confirm the new checks fail where expected.

📝 Checklist

  • I added GH Issue ID & Linear ID
  • 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.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.

#skip-changelog

@sentry

sentry Bot commented Jul 8, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

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

⚙️ sentry-android Build Distribution Settings

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 310.10 ms 352.13 ms 42.03 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
bbc35bb 324.88 ms 425.73 ms 100.85 ms
abfcc92 304.04 ms 370.33 ms 66.29 ms
94bff8d 313.23 ms 352.77 ms 39.54 ms
fcec2f2 311.35 ms 384.94 ms 73.59 ms
d15471f 304.55 ms 408.43 ms 103.87 ms
4c04bb8 307.93 ms 362.34 ms 54.41 ms
b936425 302.69 ms 372.86 ms 70.17 ms
d501a7e 314.55 ms 343.34 ms 28.79 ms
72020f8 312.32 ms 370.94 ms 58.62 ms
6b019b7 319.84 ms 333.15 ms 13.31 ms

App size

Revision Plain With Sentry Diff
bbc35bb 1.58 MiB 2.12 MiB 553.01 KiB
abfcc92 1.58 MiB 2.13 MiB 557.31 KiB
94bff8d 1.58 MiB 2.20 MiB 635.37 KiB
fcec2f2 1.58 MiB 2.12 MiB 551.51 KiB
d15471f 1.58 MiB 2.13 MiB 559.54 KiB
4c04bb8 0 B 0 B 0 B
b936425 0 B 0 B 0 B
d501a7e 0 B 0 B 0 B
72020f8 1.58 MiB 2.19 MiB 620.21 KiB
6b019b7 0 B 0 B 0 B

Previous results on branch: ci/java8-api-compatibility

Startup times

Revision Plain With Sentry Diff
29117d4 315.09 ms 353.43 ms 38.34 ms
e122d12 360.71 ms 433.96 ms 73.25 ms
609df4f 315.04 ms 360.96 ms 45.92 ms

App size

Revision Plain With Sentry Diff
29117d4 0 B 0 B 0 B
e122d12 0 B 0 B 0 B
609df4f 0 B 0 B 0 B

@adinauer

adinauer commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

Tested this using #5746 and it failed for both Math.floorDiv and Objects.requireNonNullElse in different modules.

@adinauer adinauer force-pushed the ci/java8-api-compatibility branch from 3611c33 to 0229500 Compare July 8, 2026 14:09
@adinauer adinauer changed the title ci: Add Java 8 API compatibility check build: Add Java 8 API compatibility checks Jul 8, 2026
Apply Animal Sniffer to Java 8 JVM SDK modules and check them against the Codehaus Java 8 runtime signature. This catches references to newer JDK APIs while keeping the existing Android signature checks in place where they already apply.

Refs GH-5741
@adinauer adinauer force-pushed the ci/java8-api-compatibility branch from 0229500 to 305dafe Compare July 8, 2026 14:23
Comment thread sentry-apache-http-client-5/build.gradle.kts Outdated
Comment thread sentry-apache-http-client-5/build.gradle.kts Outdated
adinauer and others added 2 commits July 9, 2026 09:58
Move shared Java 8 API compatibility configuration into build-logic plugins. Apply the Android-compatible variant where modules also need gummy-bears API checks to reduce duplicated signature setup.

Co-Authored-By: Claude <noreply@anthropic.com>
Move Java 8 signature coordinates into the version catalog and add a shared helper for registering Animal Sniffer signature dependencies.

Co-Authored-By: Claude <noreply@anthropic.com>
dependsOn("animalsnifferMain")
}

project.afterEvaluate {

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.

why do we need the afterEvaluate here? in general afterEvaluate is bad for performance and build consistency and should be avoided.

exclude(extension.mainExcludes.get())
val ignoredClasses = extension.ignoredClasses.get()
if (ignoredClasses.isNotEmpty()) {
javaClass.getMethod("setIgnoreClasses", Iterable::class.java).invoke(this, ignoredClasses)

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.

why do we need to use reflection here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

updated

adinauer and others added 2 commits July 9, 2026 14:43
Configure Animal Sniffer tasks with the plugin task type directly so ignored classes can be set without reflective method lookup.

Co-Authored-By: Claude <noreply@anthropic.com>
Configure Animal Sniffer task options directly from the convention extension so the build does not defer configuration with afterEvaluate.

Co-Authored-By: Claude <noreply@anthropic.com>
@adinauer adinauer marked this pull request as ready for review July 9, 2026 13:56
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.

2 participants