Skip to content

fix(build): Strip MethodParameters so AGP 8.0 and older can dex the SDK - #6356

Open
antonis wants to merge 5 commits into
mainfrom
fix/strip-method-parameters
Open

antonis wants to merge 5 commits into
mainfrom
fix/strip-method-parameters

Conversation

@antonis

@antonis antonis commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

📜 Description

Removes the MethodParameters attribute from the Java classes of every published module, right after JavaCompile runs. The new StripMethodParameters action in build-logic uses ASM 9.9 (the version AGP already brings) to rewrite only the class files that have the attribute. The JdkTargetConvention plugin attaches it to every JavaCompile task of modules that apply com.vanniktech.maven.publish, including the Android compile*JavaWithJavac tasks.

No published module compiles with -parameters, so the attribute only holds the nameless entries javac 21 adds. Removing it loses nothing, and the output matches what javac 17 produced for 8.61.0. Kotlin output is unaffected.

The publish gate is necessary: the action removes all entries, also the named ones that -parameters writes. The Spring Boot samples do apply the Spring Boot Gradle plugin, which adds -parameters, and Spring resolves handler and bean parameters by name at start-up. A commit on this branch that ran the action on every module broke the 4 kafka-profile Spring system tests, because the sample apps did not start. The StripMethodParameters KDoc now records that constraint.

💡 Motivation and Context

Since the move to a JDK 21 toolchain in #6242, javac writes MethodParameters entries without a name for synthetic and mandated parameters, such as bridge methods (JDK-8292275). D8 older than 8.1 (AGP 8.0 and older) crashes on them with NullPointerException: Cannot invoke "String.length()", so release builds of those apps fail on 8.61.1. React Native reverted its bump in getsentry/sentry-react-native#6931 because of this.

💚 How did you test it?

Built with a JDK 21 toolchain and checked the classes with javap -v:

Artifact MethodParameters D8 3.3.75 (AGP 7.3)
Published sentry-8.61.1.jar 141 classes NPE
sentry jar from this branch 0 dexes fine
sentry-android-core AAR from this branch 0 dexes fine
  • The attribute stays stripped after a forced recompile (--rerun), with configuration cache enabled.
  • spotlessApply apiDump produced no changes to the .api files.

ASM changes nothing else. The same pipeline was run twice over all 781 classes of sentry-8.60.0.jar: once as the stripper, once as a pure round trip that keeps visitParameter. Comparing sorted javap -p -v -c output of input and output, 5 of 781 classes differ, and only because ASM drops an empty LocalVariableTable from synthetic switch-map initializers. Constant pool indices, code, frames, line numbers, signatures and annotations stay the same. The byte-level diff is larger, but that is attribute order only. On JDK 21 test classes (enum, inner class, bridge method, record), the stripper removes the MethodParameters blocks and nothing else.

Published test code is safe. Published modules hold 6 Java test files (vendored gson tests and generated Apollo classes); the rest of the test sources are Kotlin. :sentry-apollo:test and :sentry:test --tests "*vendor*" pass with the action attached to the test compile tasks.

Samples keep their parameter names. After a clean rebuild, sentry-samples-spring-boot-jakarta PersonController again has its MethodParameters blocks with the real names (personService, id).

The MethodParameters string can stay in the constant pool of rewritten classes, because the ClassWriter copies it from the reader. Check for the attribute with javap -v, not grep.

📝 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.

🔮 Next steps

  • Add a CI check that fails if a published class has a MethodParameters attribute again, or that dexes the artifacts with an old D8.
  • Add a build-logic test for the ASM round trip, so a future ASM upgrade cannot change bytecode unnoticed.
  • The system test job does not keep the start-up log of the sample apps, so a start-up failure gives no error message. Worth saving.
  • After a release with this fix, React Native can bump to it and skip 8.61.1.

🤖 Generated with Claude Code

antonis and others added 2 commits October 22, 2026 13:41
javac 21 writes nameless MethodParameters entries for synthetic and
mandated parameters (JDK-8292275), which crash D8 older than 8.1 with
a NullPointerException. Remove the attribute from the main Java classes
of published modules after compiling, restoring the javac 17 output.

Fixes #6355

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sentry

sentry Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

📲 Install Builds

Android

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

⚙️ sentry-android Build Distribution Settings

@antonis

antonis commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Closing for now since the impact of the issue seems to be small

@antonis antonis closed this Oct 22, 2026
@antonis antonis reopened this Oct 22, 2026
@markushi
markushi marked this pull request as ready for review October 22, 2026 14:29
@sentry-junior

sentry-junior Bot commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

PR shepherd — head e5e54aee, mergeable

Check Class Diagnosis
system-test (sentry-samples-spring-boot-4, false, true) code The Spring app never became ready (20/20 readiness attempts), so no tests ran.
system-test (sentry-samples-spring-boot-4-opentelemetry, true, false) code Same: the app fails to start.
system-test (sentry-samples-spring-boot-jakarta, false, true) code Same: the app fails to start.
system-test (sentry-samples-spring-boot-jakarta-opentelemetry, true, false) code Same: the app fails to start.

All 4 failing jobs run with the kafka Spring profile, and all 4 passed on the previous head 79da542c. The likely cause is this head commit: StripMethodParameters now runs on every JavaCompile task, including the Spring sample apps. The Spring Boot Gradle plugin compiles those apps with -parameters, and Spring can rely on parameter names at startup (for example in Kafka listener or configuration binding). This is an inference: I couldn't see the app's startup error, because the job doesn't upload the Spring server log.

Actions: none. This needs a decision about the change itself (for example, keep the stripping limited to published or non-Spring modules), so I didn't re-run or push anything.

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.

8.61.1 fails to dex on AGP 8.0 and older: D8 NullPointerException "Cannot invoke String.length()"

2 participants