Where are generic types stored in java class files?

前端 未结 2 858
生来不讨喜
生来不讨喜 2020-11-28 10:46

I am well aware that generic types are erased from Java code when it is compiled. What information (attributes?) do 1.5+ JVMs use to implement getGenericType ,

2条回答
  •  生来不讨喜
    2020-11-28 11:35

    Java generics are indeed implemented by type erasure, so there is no type information in the bytecode.

    For example, let's take a look two classes which declare a List field, one in generic and the other in non-generic form:

    class NonGeneric {
        List list;
    }
    

    And,

    class Generic {
        List list;
    }
    

    In both cases, the resulting bytecode is the following:

      Code:
       Stack=3, Locals=1, Args_size=1
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."":()V
       4:   aload_0
       5:   new #2; //class java/util/ArrayList
       8:   dup
       9:   invokespecial   #3; //Method java/util/ArrayList."":()V
       12:  putfield    #4; //Field list:Ljava/util/List;
       15:  return
    

    There is no reference to the String type used in the ArrayList nor List. So, we can see that generics is indeed implemented by type erasure.

    However, if we look at the constant pool, we can find a difference.

    The non-generic constant pool:

      Constant pool:
    const #1 = Method   #6.#15; //  java/lang/Object."":()V
    const #2 = class    #16;    //  java/util/ArrayList
    const #3 = Method   #2.#15; //  java/util/ArrayList."":()V
    const #4 = Field    #5.#17; //  NonGeneric.list:Ljava/util/List;
    const #5 = class    #18;    //  NonGeneric
    const #6 = class    #19;    //  java/lang/Object
    const #7 = Asciz    list;
    const #8 = Asciz    Ljava/util/List;;
    const #9 = Asciz    ;
    const #10 = Asciz   ()V;
    // snip the rest //
    

    The generic constant pool:

      Constant pool:
    const #1 = Method   #6.#17; //  java/lang/Object."":()V
    const #2 = class    #18;    //  java/util/ArrayList
    const #3 = Method   #2.#17; //  java/util/ArrayList."":()V
    const #4 = Field    #5.#19; //  Generic.list:Ljava/util/List;
    const #5 = class    #20;    //  Generic
    const #6 = class    #21;    //  java/lang/Object
    const #7 = Asciz    list;
    const #8 = Asciz    Ljava/util/List;;
    const #9 = Asciz    Signature;
    const #10 = Asciz   Ljava/util/List;;
    const #11 = Asciz   ;
    const #12 = Asciz   ()V;
    // snip the rest//
    

    As can be seen, in the Generic class, we can see there are two extra constants, #9 and #10, in the constant pool, which mentions that the List has the generic type of String.

    (And incorporating new knowledge that I learned from Chris Jester-Young's answer)

    Looking further at the disassembly of the class file, there is a reference to the constant #10 right before the Code: block of the Generic class:

    java.util.List list;
      Signature: length = 0x2
       00 0A 
    

    The hexadecimal value 0A is 10 in decimal, which refers to the constant pool #10:

    const #10 = Asciz   Ljava/util/List;;
    

    Therefore, the information from the constant pool is used in order to indicate that a field is of a generic type.

提交回复
热议问题