【问题标题】:How do we see the bytecode generated by the compiler for type erasure in Java [duplicate]我们如何查看编译器为 Java 中的类型擦除生成的字节码 [重复]
【发布时间】:2012-07-16 10:04:52
【问题描述】:

可能重复:
How to view Java's byte code?

我想知道类型擦除后是否可以在类文件中看到java编译器所做的代码更改。

我尝试过 javap,但它使用参数化类型重建了原始源文件。

教程 (http://docs.oracle.com/javase/tutorial/java/generics/genTypes.html) 讨论了在类型擦除后用有界类型或对象替换参数化类型。我想看看编译器做了哪些更改,这些更改在 javap 或任何反编译器中都不可见。

问候, 萨特维克

【问题讨论】:

  • 感谢您的快速回复,我还使用了除 javap 之外的反编译器(Jad-Gui)来查看字节码。但它没有显示我在寻找什么。

标签: java type-erasure


【解决方案1】:

类型擦除字面意思是从生成的字节码中删除泛型类型。值得注意的是它的缺席。因此,您可以看到它在字节码中不存在。

当您使用javap 时,您会看到一些通用类型信息可用于类、方法和字段签名。这包括在内,因此编译器可以使用这些类完成其编译代码的工作。它们在运行时不做任何事情,尽管它们可以通过反射获得,因此您可以编写一个使用此信息的库。

【讨论】:

  • OP 可能感兴趣的正是某个泛型类型擦除成的类型。
  • 非泛型类型,即擦除<Generic>位;)
  • 还有更多内容:MyClass<T extends List> { T getList(); } 擦除为 List getList(); -- 这只是最简单的例子。
  • 嗨,Marko,这是我从 javap 的输出中查找的信息。我对指令集不是很熟悉。有没有更简单的方法来理解 javap 的输出。我希望反编译器可能会以更易读的方式显示这些更改。
  • @Sathwik 您遇到的问题是字节码向您显示了javac 编译代码所需的所有信息以及JVM 运行代码所需的信息。它不显示,反编译器也不会只显示 JVM 实际使用的内容。
【解决方案2】:

我遇到的一个案例是Collections.max(),他们希望类型擦除为Object,但仍强制它为Comparable。你可以看到这样的签名:

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);

另一种方法是使用javap -c 并查看编译器进行的检查。示例:

对于这个程序:

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());
    }
}

你会得到以下结果:

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

}

注意checkcast

【讨论】:

    猜你喜欢
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    • 2018-01-31
    • 1970-01-01
    • 2023-04-07
    相关资源
    最近更新 更多