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 ,
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.