Last active
August 29, 2015 14:15
-
-
Save marchof/070ee2c2077bd095ba96 to your computer and use it in GitHub Desktop.
Reproducer for invalid annotation ranges on bridge methods (javac 1.8.0_31)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PROBLEM | |
Annotation with target TYPE_USE seems to be copied to bridge methods. As bridge methods | |
only delegate back to the overloaded method, these annotations are typically invalid. | |
The reproducer shows that the type annotations specifies a PC range which is longer | |
than the byte code of the method. | |
Probably type annotations shouldn't be copied to bridge methods. | |
REPRODUCER | |
The annotation with target TYPE_USE in the method doit(java.lang.Runnable) is copied | |
to the bridge method doit(java.lang.Object). While the bridge method only has 8 | |
instructions, the range of the type annotation has a length of 15. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Classfile ClassWithBridgeMethod.class | |
Last modified 19.02.2015; size 654 bytes | |
MD5 checksum b81ccd384e2806ff7c6c08741412ddbb | |
public class ClassWithBridgeMethod<T extends java.lang.Runnable> extends java.lang.Object implements ParameterizedInterface<T> | |
minor version: 0 | |
major version: 52 | |
flags: ACC_PUBLIC, ACC_SUPER | |
Constant pool: | |
#1 = Methodref #7.#20 // java/lang/Object."<init>":()V | |
#2 = Fieldref #21.#22 // java/lang/System.out:Ljava/io/PrintStream; | |
#3 = Methodref #23.#24 // java/io/PrintStream.println:(Ljava/lang/Object;)V | |
#4 = Class #25 // java/lang/Runnable | |
#5 = Methodref #6.#26 // ClassWithBridgeMethod.doit:(Ljava/lang/Runnable;)V | |
#6 = Class #27 // ClassWithBridgeMethod | |
#7 = Class #28 // java/lang/Object | |
#8 = Class #29 // ParameterizedInterface | |
#9 = Utf8 <init> | |
#10 = Utf8 ()V | |
#11 = Utf8 Code | |
#12 = Utf8 doit | |
#13 = Utf8 (Ljava/lang/Runnable;)V | |
#14 = Utf8 RuntimeInvisibleTypeAnnotations | |
#15 = Utf8 LTypeUseAnnotation; | |
#16 = Utf8 Signature | |
#17 = Utf8 (TT;)V | |
#18 = Utf8 (Ljava/lang/Object;)V | |
#19 = Utf8 <T::Ljava/lang/Runnable;>Ljava/lang/Object;LParameterizedInterface<TT;>; | |
#20 = NameAndType #9:#10 // "<init>":()V | |
#21 = Class #30 // java/lang/System | |
#22 = NameAndType #31:#32 // out:Ljava/io/PrintStream; | |
#23 = Class #33 // java/io/PrintStream | |
#24 = NameAndType #34:#18 // println:(Ljava/lang/Object;)V | |
#25 = Utf8 java/lang/Runnable | |
#26 = NameAndType #12:#13 // doit:(Ljava/lang/Runnable;)V | |
#27 = Utf8 ClassWithBridgeMethod | |
#28 = Utf8 java/lang/Object | |
#29 = Utf8 ParameterizedInterface | |
#30 = Utf8 java/lang/System | |
#31 = Utf8 out | |
#32 = Utf8 Ljava/io/PrintStream; | |
#33 = Utf8 java/io/PrintStream | |
#34 = Utf8 println | |
{ | |
public ClassWithBridgeMethod(); | |
descriptor: ()V | |
flags: ACC_PUBLIC | |
Code: | |
stack=1, locals=1, args_size=1 | |
0: aload_0 | |
1: invokespecial #1 // Method java/lang/Object."<init>":()V | |
4: return | |
public void doit(T); | |
descriptor: (Ljava/lang/Runnable;)V | |
flags: ACC_PUBLIC | |
Code: | |
stack=2, locals=3, args_size=2 | |
0: aconst_null | |
1: astore_2 | |
2: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; | |
5: aload_2 | |
6: invokevirtual #3 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V | |
9: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; | |
12: aload_2 | |
13: invokevirtual #3 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V | |
16: return | |
RuntimeInvisibleTypeAnnotations: | |
0: #15(): LOCAL_VARIABLE, {start_pc=2, length=15, index=2} | |
Signature: #17 // (TT;)V | |
public void doit(java.lang.Object); | |
descriptor: (Ljava/lang/Object;)V | |
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC | |
Code: | |
stack=2, locals=2, args_size=2 | |
0: aload_0 | |
1: aload_1 | |
2: checkcast #4 // class java/lang/Runnable | |
5: invokevirtual #5 // Method doit:(Ljava/lang/Runnable;)V | |
8: return | |
RuntimeInvisibleTypeAnnotations: | |
0: #15(): LOCAL_VARIABLE, {start_pc=2, length=15, index=2} | |
} | |
Signature: #19 // <T::Ljava/lang/Runnable;>Ljava/lang/Object;LParameterizedInterface<TT;>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.annotation.ElementType; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.RetentionPolicy; | |
import java.lang.annotation.Target; | |
public class ClassWithBridgeMethod<T extends Runnable> implements ParameterizedInterface<T> { | |
@Override | |
public void doit(final T t) { | |
@TypeUseAnnotation | |
Object x = null; | |
// Some instructions just to widen the scope of annotation for x | |
System.out.println(x); | |
System.out.println(x); | |
} | |
} | |
interface ParameterizedInterface<T> { | |
void doit(T arg); | |
} | |
@Target({ ElementType.TYPE_USE }) | |
@Retention(RetentionPolicy.CLASS) | |
@interface TypeUseAnnotation { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment