Classfile type annotation for INSTANCEOF expressions

Archie Cobbs archie.cobbs at gmail.com
Mon Nov 10 20:38:10 UTC 2025


Consider this class:

import java.lang.annotation.*;
public class InstancePat {
    InstancePat(Object o) {
        if (o instanceof @Anno Runnable) {
            @Anno Runnable r = (@Anno Runnable)o;
            System.out.println(r);
        }
    }
    InstancePat(Object o, int x) {
        if (o instanceof @Anno Runnable r)
            System.out.println(r);
    }
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@interface Anno { }

Here's the javap output (edited for brevity):

  InstancePat(java.lang.Object);
         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
      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

  InstancePat(java.lang.Object, int);
         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
      RuntimeVisibleTypeAnnotations:
        0: #27(): LOCAL_VARIABLE, {start_pc=16, length=7, index=3}
          Anno

Note the RuntimeVisibleTypeAnnotations entries for INSTANCEOF and CAST have
disappeared in the second constructor. Is this behavior expected?

This question is related to my previous one about CAST expressions... both
questions ask about "holes" in the story being told by the classfile
relating to where type annotations occurred in the original source.

Stepping back, what is the actual intent here? I had assumed that, given
correct class files, a bytecode analysis tool should be able to "keep track
of" every type annotation that existed in the original source code, but
maybe I'm reading too much into things (I didn't witness the discussion
that led to these classfile attributes). Thanks for any clarifications.

-Archie

-- 
Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20251110/843af032/attachment-0001.htm>


More information about the compiler-dev mailing list