From 4dde8e8644a89c67e0269ff2e0902527d2e47ba6 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 28 Oct 2026 15:14:43 +0100 Subject: [PATCH 1/2] build(ndk): compile with -parameters for older R8 --- ndk/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndk/build.gradle.kts b/ndk/build.gradle.kts index be4a8ce147..b4e5696cae 100644 --- a/ndk/build.gradle.kts +++ b/ndk/build.gradle.kts @@ -48,7 +48,7 @@ allprojects { dependsOn("cleanTest") } withType { - options.compilerArgs.addAll(arrayOf("-Xlint:all", "-Werror", "-Xlint:-classfile", "-Xlint:-processing", "-Xlint:-options")) + options.compilerArgs.addAll(arrayOf("-Xlint:all", "-Werror", "-Xlint:-classfile", "-Xlint:-processing", "-Xlint:-options", "-parameters")) } } } From bca5fe1b903c87de226274e8b0b8109e148ef31e Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 28 Oct 2026 16:12:36 +0100 Subject: [PATCH 2/2] build(ndk): strip unnamed MethodParameters instead of -parameters --- ndk/build.gradle.kts | 2 +- ndk/lib/build.gradle.kts | 87 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/ndk/build.gradle.kts b/ndk/build.gradle.kts index b4e5696cae..be4a8ce147 100644 --- a/ndk/build.gradle.kts +++ b/ndk/build.gradle.kts @@ -48,7 +48,7 @@ allprojects { dependsOn("cleanTest") } withType { - options.compilerArgs.addAll(arrayOf("-Xlint:all", "-Werror", "-Xlint:-classfile", "-Xlint:-processing", "-Xlint:-options", "-parameters")) + options.compilerArgs.addAll(arrayOf("-Xlint:all", "-Werror", "-Xlint:-classfile", "-Xlint:-processing", "-Xlint:-options")) } } } diff --git a/ndk/lib/build.gradle.kts b/ndk/lib/build.gradle.kts index e012680e0b..4e1aa56554 100644 --- a/ndk/lib/build.gradle.kts +++ b/ndk/lib/build.gradle.kts @@ -1,4 +1,9 @@ import com.android.build.gradle.internal.lint.AndroidLintAnalysisTask +import org.objectweb.asm.ClassReader +import org.objectweb.asm.ClassVisitor +import org.objectweb.asm.ClassWriter +import org.objectweb.asm.MethodVisitor +import org.objectweb.asm.Opcodes plugins { id("com.android.library") @@ -187,3 +192,85 @@ afterEvaluate { tasks.withType().configureEach { doNotTrackState("Dependency metadata can change without code changes") } + +// keep the classes dexable by D8/R8 of AGP 8.0 and older when compiled with JDK 21+ +tasks.withType().configureEach { + doLast(StripMethodParameters()) +} + +/** + * Removes the MethodParameters attribute from methods that have a parameter without a name. + * + * Since JDK 21 (JDK-8292275) javac writes MethodParameters for synthetic or mandated parameters, + * e.g. of enums, even without `-parameters`. Those entries have no name, and the D8/R8 of AGP 8.0 + * and older crash on them. Same as getsentry/sentry-java#6356. + */ +class StripMethodParameters : Action { + override fun execute(task: Task) { + (task as JavaCompile) + .destinationDirectory + .get() + .asFile + .walkTopDown() + .filter { it.isFile && it.extension == "class" } + .forEach { file -> + val reader = ClassReader(file.readBytes()) + val methods = reader.methodsWithUnnamedParameters() + if (methods.isNotEmpty()) { + val writer = ClassWriter(reader, 0) + reader.accept( + object : ClassVisitor(Opcodes.ASM9, writer) { + override fun visitMethod( + access: Int, + name: String?, + descriptor: String?, + signature: String?, + exceptions: Array?, + ): MethodVisitor? { + val next = super.visitMethod(access, name, descriptor, signature, exceptions) + if (name + descriptor !in methods) { + return next + } + return object : MethodVisitor(Opcodes.ASM9, next) { + override fun visitParameter( + name: String?, + access: Int, + ) = Unit + } + } + }, + 0, + ) + file.writeBytes(writer.toByteArray()) + } + } + } + + private fun ClassReader.methodsWithUnnamedParameters(): Set { + val methods = mutableSetOf() + accept( + object : ClassVisitor(Opcodes.ASM9) { + override fun visitMethod( + access: Int, + name: String?, + descriptor: String?, + signature: String?, + exceptions: Array?, + ): MethodVisitor = + object : MethodVisitor(Opcodes.ASM9) { + override fun visitParameter( + parameterName: String?, + access: Int, + ) { + if (parameterName == null) { + methods.add(name + descriptor) + } + } + } + }, + // no SKIP_DEBUG, ASM counts MethodParameters as debug info + ClassReader.SKIP_CODE, + ) + return methods + } +}