5

Possible Duplicate:
How to view Java's byte code?

I want to know whether is it possible to see the code changes done by the java compiler in the class file after type erasure.

I have tried javap, but it rebuilds the original source file with the parametrized types.

The tutorial (http://docs.oracle.com/javase/tutorial/java/generics/genTypes.html) talks about replacement of parametrized type with a bounded type or an Object after type erasure. I want to see what changes are done by the compiler which is not visible with javap or any decompiler.

regards, sathwik

Community
  • 1
  • 1
Sathwik
  • 193
  • 8
  • thanks for your quick reply, I have also used a decompiler (Jad-Gui) apart from javap to see the byte code. But it doesn't show what I am looking for. – Sathwik Jul 16 '12 at 10:13

2 Answers2

1

Type erasure literally means the generic type is dropped from the resulting byte code. It is notable by its absence. As such, all you can see that it is not there in the byte code.

When you use javap, you will see that some generic type information is available for class, method and field signatures. This is included so the compiler can do its job to compile code using these classes. They don't do anything at runtime, although they are available via reflection so you can write a library which uses this information.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • The thing that OP may be interested in is exactly what type a certain generic type erases into. – Marko Topolnik Jul 16 '12 at 10:43
  • The non-generic type, i.e. erase the `` bit ;) – Peter Lawrey Jul 16 '12 at 10:53
  • 1
    There's more to it: `MyClass { T getList(); }` erases to `List getList();` -- this is just the most trivial example. – Marko Topolnik Jul 16 '12 at 10:57
  • Hi Marko, This is the kind of info i am looking from the output of javap. I am not very conversant with the instruction set. Is there a easier way to understand the output of javap. I was hoping that a decompiler would probably show these changes in a more readable manner. – Sathwik Jul 16 '12 at 11:26
  • @Sathwik the problem you have is the byte code shows you all the information the `javac` needs to compile code AND what the JVM needs to run the code. It does not show, nor will a de-compiler show, only what the JVM actually uses. – Peter Lawrey Jul 16 '12 at 11:35
  • I am following the example code provided in the tutorial http://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html – Sathwik Jul 16 '12 at 11:38
0

A case I ran into was with Collections.max() where they wanted the type erasure to be Object but still enforce it to be a Comparable. You can see the signature like so:

vlad@vld /tmp $ javap java.util.Collections | grep max
    public static java.lang.Object max(java.util.Collection);
    public static java.lang.Object max(java.util.Collection, java.util.Comparator);

An alternative is to use javap -c and see the checks put in place by the compiler. Example:

For this program:

public class Test{
    public static void main(String[]args){
        java.util.Vector<String> a = new java.util.Vector<String>();
        a.add("Hello world");
        System.out.println(a.get(0).length());
    }
}

You get the following result:

Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
  Code:
   0:    aload_0
   1:    invokespecial    #1; //Method java/lang/Object."<init>":()V
   4:    return

public static void main(java.lang.String[]);
  Code:
   0:    new    #2; //class java/util/Vector
   3:    dup
   4:    invokespecial    #3; //Method java/util/Vector."<init>":()V
   7:    astore_1
   8:    aload_1
   9:    ldc    #4; //String Hello world
   11:    invokevirtual    #5; //Method java/util/Vector.add:(Ljava/lang/Object;)Z
   14:    pop
   15:    getstatic    #6; //Field java/lang/System.out:Ljava/io/PrintStream;
   18:    aload_1
   19:    iconst_0
   20:    invokevirtual    #7; //Method java/util/Vector.get:(I)Ljava/lang/Object;
   23:    checkcast    #8; //class java/lang/String
   26:    invokevirtual    #9; //Method java/lang/String.length:()I
   29:    invokevirtual    #10; //Method java/io/PrintStream.println:(I)V
   32:    return

}

Notice the checkcast.

Vlad
  • 18,195
  • 4
  • 41
  • 71