From 9f97fb476d748a88d4e055311bd40ea18b1d4c86 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 09:04:12 +0000 Subject: [PATCH 1/2] Initial plan From b3ca2c8c96643e7b350775a8bbb5a6cddb944951 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 09:14:47 +0000 Subject: [PATCH 2/2] Fix class descriptor derivation and annotation string constant relocation Co-authored-by: Goooler <10363352+Goooler@users.noreply.github.com> --- .../gradle/plugins/shadow/RelocationTest.kt | 39 +++++++++++++++++++ .../shadow/internal/RelocatorRemapper.kt | 11 +++++- .../plugins/shadow/tasks/ShadowCopyAction.kt | 5 +-- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt index 852ebcc79..e8efaf4b2 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt @@ -533,6 +533,45 @@ class RelocationTest : BasePluginTest() { } } + @Test + fun relocateAnnotationStringConstants() { + writeClass { + """ + package my; + import java.lang.annotation.Retention; + import java.lang.annotation.RetentionPolicy; + @Retention(RetentionPolicy.RUNTIME) + @interface MyAnnotation { + String value(); + } + @MyAnnotation("foo.Bar") + public class Main { + public static void main(String[] args) { + MyAnnotation ann = Main.class.getAnnotation(MyAnnotation.class); + System.out.println(ann.value()); + } + } + """ + .trimIndent() + } + projectScript.appendText( + """ + $shadowJarTask { + manifest { + attributes '$mainClassAttributeKey': 'my.Main' + } + relocate('foo', 'shadow.foo') + } + """ + .trimIndent() + ) + + runWithSuccess(shadowJarPath) + val result = runProcess("java", "-jar", outputShadowedJar.use { it.toString() }) + + assertThat(result).contains("shadow.foo.Bar") + } + @Issue("https://github.com/GradleUp/shadow/issues/1403") @Test fun relocateMultiClassSignatureStringConstants() { diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/RelocatorRemapper.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/RelocatorRemapper.kt index c7fbaf3ae..d178d149b 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/RelocatorRemapper.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/RelocatorRemapper.kt @@ -436,7 +436,16 @@ internal class RelocatorRemapper( AnnotationValue.ofAnnotation(mapAnnotation(valObj.annotation())) is AnnotationValue.OfArray -> AnnotationValue.ofArray(valObj.values().map(this::mapAnnotationValue)) - is AnnotationValue.OfConstant -> valObj + is AnnotationValue.OfConstant -> { + if (valObj is AnnotationValue.OfString) { + val str = valObj.stringValue() + // mapLiterals=true enables the skipStringConstants check in each relocator. + val mapped = map(str, mapLiterals = true) + if (mapped != str) AnnotationValue.ofString(mapped) else valObj + } else { + valObj + } + } is AnnotationValue.OfClass -> AnnotationValue.ofClass(mapClassDesc(valObj.classSymbol())!!) is AnnotationValue.OfEnum -> AnnotationValue.ofEnum( diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.kt index a0d9d06b8..4ca734184 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.kt @@ -14,7 +14,6 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.ResourceTransform import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext import java.io.File import java.lang.classfile.ClassFile -import java.lang.constant.ClassDesc import java.util.GregorianCalendar import java.util.zip.ZipException import kotlin.metadata.jvm.KmModule @@ -212,14 +211,14 @@ constructor( file.readBytes().let { bytes -> var modified = false val multiReleasePrefix = "^META-INF/versions/\\d+/".toRegex().find(path)?.value.orEmpty() - val internalClassName = path.replace(multiReleasePrefix, "").removeSuffix(".class") val remapper = RelocatorRemapper(relocators) { modified = true } val newBytes = try { val classFile = ClassFile.of() val classModel = classFile.parse(bytes) - val newClassDesc = remapper.mapClassDesc(ClassDesc.ofInternalName(internalClassName))!! + val originalClassDesc = classModel.thisClass().asSymbol() + val newClassDesc = remapper.mapClassDesc(originalClassDesc)!! classFile.transformClass(classModel, newClassDesc, remapper.asClassTransform()) } catch (t: Throwable) { throw GradleException("Error in Class-File API processing class $path", t)