Java类常量池重复?

Nán*_*ser 7 java javac

我已经反编译了一个类,javap我在Constant Pool部分看到了一些重复,如下所示:

 #19 = Class              #350          //  java/lang/StringBuilder
... Some other class constants here
#318 = Class              #350          //  java/lang/StringBuilder
Run Code Online (Sandbox Code Playgroud)

Methodrefs仅指其中一个:

 #20 = Methodref          #19.#351      //  java/lang/StringBuilder."<init>":()V
 #22 = Methodref          #19.#353      //  java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 #24 = Methodref          #19.#355      //  java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
 #25 = Methodref          #19.#356      //  java/lang/StringBuilder.toString:()Ljava/lang/String;
#110 = Methodref          #19.#445      //  java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
Run Code Online (Sandbox Code Playgroud)

根据类文件格式,这个类是否正确?我认为每个Class只提到一次,后面由字节码部分的索引引用.

$ javac -version
javac 1.7.0_15
Run Code Online (Sandbox Code Playgroud)

另一个奇怪的事情是在javac Pool.java中代表常量池的类的源代码中.这表明它不会将对象放入池中(如果它已经存在)(借助HashMap).我想知道这些类的equals()/ hashCode()方法是否正确实现.

Rav*_*edi 2

你是对的。Constant pool不需要重复条目。一个类在常量池中只能有 1 个条目。

这看起来绝对是一个错误。看一下这个。有人已将此记录为错误并且已被确认 >> https://bugs.java.com/bugdatabase/view_bug?bug_id=6746955

答案更新:

我想在这里指出的另一件事是,添加重复条目没有任何意义,因为它增加了类文件的字节大小,并且破坏了 java 类文件的紧凑性、可移植性和更快的网络移动性的主要目的。类文件应该尽可能紧凑。

顺便说一句,类文件是有效的,因为它遵循定义的类文件格式。但这并不是一个理想的。

我忘记了,回答你的第二个问题:

JVM 为看起来相似的对象分配相同的哈希码,但它们仍然是不同的。JVM 永远不会创建两个相同的对象,除非它们都引用同一个对象。哈希码只不过是一个分区系统。外观相似的对象被放置在同一分区中,以便在搜索特定对象时遍历时间变得更少。哈希码只不过是指向该小分区的指针。

只是因为不可能为每个新对象分配不同的哈希码(因为对象的数量可能超过创建唯一哈希码的可能数量。请参阅哈希算法中可能的冲突),您可能会发现具有相同哈希码的不同对象。但事情是这样的,指向内存中相同引用的两个对象必须具有相同的哈希码。

因此,从这个故事的寓意来看,JVM 确保两个不同的对象永远不会相同,即使它们的哈希码相同。