Java类常量池重复?

时间:2013-05-22 08:46:09

标签: java javac

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

 #19 = Class              #350          //  java/lang/StringBuilder
... Some other class constants here
#318 = Class              #350          //  java/lang/StringBuilder

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;

根据The class File Format,此课程是否正确?我认为每个Class只提到一次,后面由字节码部分的索引引用。

$ javac -version
javac 1.7.0_15

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

3 个答案:

答案 0 :(得分:3)

据我从JVM规范中了解,没有这样的限制可以防止常量池中的重复条目。 通常,生成类文件的编译器没有重复项。但即使类文件有重复,也不应影响其预期的行为。

您反编译的类文件是如何创建的?

答案 1 :(得分:1)

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

这肯定是一个错误。看一下这个。有人将此记录为bug并且已被确认&gt;&gt; http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6746955

答案已更新:

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

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

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

JVM为类似的对象分配相同的哈希码,但它们仍然是不同的。除非两者都指向同一对象,否则JVM永远不会创建两个相同的对象。 Hashcode只不过是一个分区系统。类似的查找对象被放置在相同的分区中,以便在搜索特定对象时遍历时间变短。 Hashcode只是指向那个小分区的指针。

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

所以,故事的道德,JVM确保两个不同的对象永远不会相同,即使它们的哈希码是。

答案 2 :(得分:0)

注意:根据JENKINS-22525,似乎虽然具有此类重复项的类文件在技术上是合法的,但IBM的J9 VM在某些情况下会拒绝加载其内部类,使用

进行观察
java.lang.IncompatibleClassChangeError: incompatible InnerClasses attribute between …