Consider this input:
import java.lang.annotation.*;
public class Test {
// Traditional instanceof+cast
Test(Object o) {
if (o instanceof @Anno Runnable) {
@Anno Runnable r = (@Anno Runnable)o;
System.out.println(r);
}
}
// Pattern matching instanceof
Test(Object o, int x) {
if (o instanceof @Anno Runnable r)
System.out.println(r);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@interface Anno { }
The @Anno type annotations on "Runnable" should be noted in the generated class file as a "RuntimeVisibleTypeAnnotations" code attribute, pointing to the corresponding CHECKCAST and INSTANCEOF instructions.
This works properly for the first constructor, which uses the traditional instanceof + cast sequence, but in the second constructor, which uses the newer instanceof pattern matching, the RuntimeVisibleTypeAnnotations for the instanceof and (implicit) cast operations are missing:
Test(java.lang.Object);
descriptor: (Ljava/lang/Object;)V
flags: (0x0000)
Code:
stack=2, locals=3, args_size=2
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_1
5: instanceof #7 // class java/lang/Runnable
8: ifeq 23
11: aload_1
12: checkcast #7 // class java/lang/Runnable
15: astore_2
16: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_2
20: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
23: return
LineNumberTable:
line 5: 0
line 6: 4
line 7: 11
line 8: 16
line 10: 23
StackMapTable: number_of_entries = 1
frame_type = 255 /* full_frame */
offset_delta = 23
locals = [ class Test, class java/lang/Object ]
stack = []
RuntimeVisibleTypeAnnotations:
0: #27(): INSTANCEOF, offset=5
Anno
1: #27(): CAST, offset=12, type_index=0
Anno
2: #27(): LOCAL_VARIABLE, {start_pc=16, length=7, index=2}
Anno
Test(java.lang.Object, int);
descriptor: (Ljava/lang/Object;I)V
flags: (0x0000)
Code:
stack=2, locals=4, args_size=3
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_1
5: instanceof #7 // class java/lang/Runnable
8: ifeq 23
11: aload_1
12: checkcast #7 // class java/lang/Runnable
15: astore_3
16: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_3
20: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
23: return
LineNumberTable:
line 13: 0
line 14: 4
line 15: 16
line 16: 23
StackMapTable: number_of_entries = 1
frame_type = 255 /* full_frame */
offset_delta = 23
locals = [ class Test, class java/lang/Object, int ]
stack = []
RuntimeVisibleTypeAnnotations:
0: #27(): LOCAL_VARIABLE, {start_pc=16, length=7, index=3}
Anno
import java.lang.annotation.*;
public class Test {
// Traditional instanceof+cast
Test(Object o) {
if (o instanceof @Anno Runnable) {
@Anno Runnable r = (@Anno Runnable)o;
System.out.println(r);
}
}
// Pattern matching instanceof
Test(Object o, int x) {
if (o instanceof @Anno Runnable r)
System.out.println(r);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@interface Anno { }
The @Anno type annotations on "Runnable" should be noted in the generated class file as a "RuntimeVisibleTypeAnnotations" code attribute, pointing to the corresponding CHECKCAST and INSTANCEOF instructions.
This works properly for the first constructor, which uses the traditional instanceof + cast sequence, but in the second constructor, which uses the newer instanceof pattern matching, the RuntimeVisibleTypeAnnotations for the instanceof and (implicit) cast operations are missing:
Test(java.lang.Object);
descriptor: (Ljava/lang/Object;)V
flags: (0x0000)
Code:
stack=2, locals=3, args_size=2
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_1
5: instanceof #7 // class java/lang/Runnable
8: ifeq 23
11: aload_1
12: checkcast #7 // class java/lang/Runnable
15: astore_2
16: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_2
20: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
23: return
LineNumberTable:
line 5: 0
line 6: 4
line 7: 11
line 8: 16
line 10: 23
StackMapTable: number_of_entries = 1
frame_type = 255 /* full_frame */
offset_delta = 23
locals = [ class Test, class java/lang/Object ]
stack = []
RuntimeVisibleTypeAnnotations:
0: #27(): INSTANCEOF, offset=5
Anno
1: #27(): CAST, offset=12, type_index=0
Anno
2: #27(): LOCAL_VARIABLE, {start_pc=16, length=7, index=2}
Anno
Test(java.lang.Object, int);
descriptor: (Ljava/lang/Object;I)V
flags: (0x0000)
Code:
stack=2, locals=4, args_size=3
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_1
5: instanceof #7 // class java/lang/Runnable
8: ifeq 23
11: aload_1
12: checkcast #7 // class java/lang/Runnable
15: astore_3
16: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_3
20: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
23: return
LineNumberTable:
line 13: 0
line 14: 4
line 15: 16
line 16: 23
StackMapTable: number_of_entries = 1
frame_type = 255 /* full_frame */
offset_delta = 23
locals = [ class Test, class java/lang/Object, int ]
stack = []
RuntimeVisibleTypeAnnotations:
0: #27(): LOCAL_VARIABLE, {start_pc=16, length=7, index=3}
Anno