Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generics Type Erasure byte code

As per the java documentation on Erasure of Generic Types,

Consider the following generic class that represents a node in a singly linked list:

public class Node<T> {

    private T data;
    private Node<T> next;

    public Node(T data, Node<T> next) }
        this.data = data;
        this.next = next;
    }

    public T getData() { return data; }
    // ...
}

Because the type parameter T is unbounded, the Java compiler replaces it with Object:

public class Node {

    private Object data;
    private Node next;

    public Node(Object data, Node next) {
        this.data = data;
        this.next = next;
    }

    public Object getData() { return data; }
    // ...
}

But after compilation with Java 1.7.0_11, when I opened it with any decompiler I can see the same code as like source code.

public class Node<T>
{
  private T data;
  private Node<T> next;

  public Node(T paramT, Node<T> paramNode)
  {
    this.data = paramT;
    this.next = paramNode;
  }

  public T getData()
  {
    return this.data;
  }
}

If Type-Erasure applied at compile then the byte code must not contain Generic information as shown above. Kindly clarify me.

NOTE: I am using JD-GUI as a decompiler to analyze the byte code

like image 482
Baji Shaik Avatar asked Mar 31 '15 18:03

Baji Shaik


People also ask

How generics works in Java What is type erasure?

Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. To implement generics, the Java compiler applies type erasure to: Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded.

What are the two 2 types of Erasure?

- Erasure is a type of alteration in document. It can be classified as chemical erasure and physical erasure.

Is reified generics and type erased generics are same?

The whole point is that reified generics have support in the compiler for preserving type information, whereas type erased generics don't. AFAIK, the whole point of having type erasure in the first place was to enable backwards compatibility (e.g. lower versioned JVMs could still understand generic classes).

What is meant by reified generics in Java?

Reified Generics is a generics system that makes generics type information available at runtime. C# is one language that supports Reified Generics natively, as opposed to Java's Type-Erased Generics.


2 Answers

The bytecode contains meta information about the code itself, such as generic types (or variable names) - it does not mean it's useable by the JVM.

The disassembled bytecode of your class looks like below (you can see it with javap -c Node.class):

public class Node<T> {
  public Node(T, Node<T>);
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: aload_1
       6: putfield      #2                  // Field data:Ljava/lang/Object;
       9: aload_0
      10: aload_2
      11: putfield      #3                  // Field next:LNode;
      14: return

  public T getData();
    Code:
       0: aload_0
       1: getfield      #2                  // Field data:Ljava/lang/Object;
       4: areturn
}

You can see that the methods and arguments generic types are there but the code itself refers to Object as expected due to the erasure process.

like image 120
assylias Avatar answered Oct 23 '22 21:10

assylias


The fact that the class is generic is retained. For instance, at runtime you can call

Node.class.getTypeParameters()

The next bit of code will return "T".

(new Node<Integer>()).getClass().getTypeParameters()[0].getName()

You can't get the value of type parameters at runtime, but the JVM knows they're there.

Erasure comes into play when you construct a instance.

Node<Integer> node = new Node<Integer>(1, null);
Integer i = node.getData();

Becomes

Node node = new Node(1, null);
Integer i = (Integer)node.getData();

Generic classes are always generic. But instances do not carry generic type information inside them. The compiler verifies that everything you've done agrees with the generic type and then inserts casts.

like image 34
axblount Avatar answered Oct 23 '22 23:10

axblount