You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The following Kotlin code is compiled with an inner class named $serializer by the Kotlin compiler.
packagefoo
@Serializable // This annotation instructs the compiler to generate an extra inner class named `$serializer`enumclassMyEnum {
VALUE1
}
The qualified name of the inner class will be foo.MyEnum$$serializer.
If relocation is enabled, shadow runs RelocatorRemapper on the class. In org.objectweb.asm.commons.Remapper, it maps inner class names by substring-ing the name after the last $. So the resultant qualified name for the example will be foo.MyEnum$serializer (Note one $ is missing). This breaks Kotlin's class metadata and will cause AssertionError in runtime. See relevant issues like mamoe/mirai#2230.
Here's the org.objectweb.asm.commons.Remapper.mapInnerClassName for your reference.
/** * Maps an inner class name to its new name. The default implementation of this method provides a * strategy that will work for inner classes produced by Java, but not necessarily other * languages. Subclasses can override. * * @param name the fully-qualified internal name of the inner class. * @param ownerName the internal name of the owner class of the inner class. * @param innerName the internal name of the inner class. * @return the new inner name of the inner class. */publicStringmapInnerClassName(
finalStringname, finalStringownerName, finalStringinnerName) {
finalStringremappedInnerName = this.mapType(name);
if (remappedInnerName.contains("$")) {
intindex = remappedInnerName.lastIndexOf('$') + 1;
while (index < remappedInnerName.length()
&& Character.isDigit(remappedInnerName.charAt(index))) {
index++;
}
returnremappedInnerName.substring(index);
} else {
returninnerName;
}
}
Shadow Version
7.1.2
Gradle Version
7.3.0
Expected Behavior
Code runs successfully.
Actual Behavior
Gradle Build Script(s)
Content of Shadow JAR (jar tf <jar file> - post link to GIST if too long)
The text was updated successfully, but these errors were encountered:
Him188
changed the title
Relocation breaks serializers compiled by kotlinx-serialization and cause AssertionError in runtime
Relocation breaks inner classes which contains '$' in name
Sep 13, 2022
The following Kotlin code is compiled with an inner class named
$serializer
by the Kotlin compiler.The qualified name of the inner class will be
foo.MyEnum$$serializer
.If relocation is enabled, shadow runs
RelocatorRemapper
on the class. Inorg.objectweb.asm.commons.Remapper
, it maps inner class names by substring-ing the name after the last$
. So the resultant qualified name for the example will befoo.MyEnum$serializer
(Note one$
is missing). This breaks Kotlin's class metadata and will causeAssertionError
in runtime. See relevant issues like mamoe/mirai#2230.Here's the
org.objectweb.asm.commons.Remapper.mapInnerClassName
for your reference.Shadow Version
7.1.2
Gradle Version
7.3.0
Expected Behavior
Code runs successfully.
Actual Behavior
Gradle Build Script(s)
Content of Shadow JAR (
jar tf <jar file>
- post link to GIST if too long)The text was updated successfully, but these errors were encountered: