Proguard corrupts...
Java class file shrinker, optimizer, obfuscator, and preverifier
Brought to you by:
guardsquare
On attempt to obfuscate bytecode for next Java enum class I got corrupted RuntimeInvisibleParameterAnnotations/RuntimeVisibleParameterAnnotations fields
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public enum AnnotationInEnumConstructor {
OK("123");
@Retention(RetentionPolicy.CLASS)
public @interface Foo {}
AnnotationInEnumConstructor(@Foo String foo) {}
public static void main(String[] args) {
}
}
Bytecode produced by java compiler:
private AnnotationInEnumConstructor(java.lang.String);
descriptor: (Ljava/lang/String;ILjava/lang/String;)V
flags: (0x0002) ACC_PRIVATE
....
Signature: #33 // (Ljava/lang/String;)V
RuntimeInvisibleParameterAnnotations:
parameter 0:
0: #35()
AnnotationInEnumConstructor$Foo
After obfuscation:
private AnnotationInEnumConstructor(java.lang.String);
descriptor: (Ljava/lang/String;ILjava/lang/String;)V
....
RuntimeInvisibleParameterAnnotations:
parameter 0:
parameter 1:
parameter 2:
0: #38()
AnnotationInEnumConstructor$Foo
Signature: #25 // (Ljava/lang/String;)V
With 'Runtime' retention for annotations, next code works differently before and after obfuscations of AnnotationInEnumConstructor.class:
Same problem with inner classes:
Before transformation:
After transformation
Thanks for your detailed report. I can reproduce the output. It appears that javap helpfully prints out its own interpretation of the RuntimeInvisibleParameterAnnotations attribute. Based on the preceding Signature attribute it prints out that Foo is an annotation for parameter #0, although the bytecode does specify that it is an annotation for parameter #2. With ProGuard's raw bytecode dump (-dontshrink -dontoptimize -dontobfuscate -dontpreverify -dump), you can see essentially the same bytecode before and after processing:
Attributes in original code
Attributes in processed code
I assume the difference with javap is caused by the order of the attributes, which should never matter. The question is now: does it matter to the JVM and do you get any issues at runtime?
Oops, I see your example now. We'll investigate.
The problem is caused by JVM correlating the annotations with the method's signature attribute, instead of the method descriptor. This is a long-standing unresolved issue in the JDK, eg. JDK-8024694 and JDK-8062582. We'll see if we can avoid it.
The problem has now been fixed for the upcoming ProGuard 6.1.0 beta2.
ProGuard 6.1.0 beta2 cannot be resolved, when it will be ready to download ? Thanks for your great work