没有在字节码中扩展java.lang.Object。那么为什么编译器没有在较新版本的java中添加它?

时间:2015-02-05 10:33:21

标签: java bytecode

我的代码简单如下

package prashant;
public class CheckObject {
}

我使用了 javap -c CheckObject 并得到了字节码:

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

与旧版本的Java一样,隐式编译器在字节代码中添加 extends Object

  

public class prashant.CheckObject extends java.lang.Object

所以我有两个关于 extends Object 的问题:

1)是否因为性能受到影响而没有添加?

2)改变了哪个java版本?

用于编译此代码的java版本是 1.6.0_45

3 个答案:

答案 0 :(得分:4)

您正在打印反汇编,而不是原始字节码,并且反汇编设计为人类可读的。没有声明超类的对象必须extends Object(如构造函数的注释所示),因此列出它是多余的。

答案 1 :(得分:2)

首先,每个类必须有一个超类(java/lang/Object本身除外)。关于这一点没有任何改变。

问题是你正在使用专为Java程序员设计的javap,因此往往会隐藏类文件格式的不方便细节,使输出看起来更像Java。如果你想查看类文件中的真实内容,你需要使用不同的反汇编程序(such as the Krakatau disassembler)。

据推测,javap的旧版本没有隐藏Object超类,但后来更新了它们以隐藏它们。你的分类文件没有变化,只有你的反汇编程序。

答案 2 :(得分:1)

不考虑编译器是否确实改变 1 的问题......这种改变几乎无关紧要。

  • 如果没有对Object构造函数的显式调用,它会在类文件中保存少量空间。保存4个字节的字节码,并且(我认为)构造函数签名的一个常量池条目。

  • 当字节码仍然被解释时,可能在执行显式构造函数调用的执行速度方面与隐式构造函数调用略有不同。但差异可以忽略不计,而且我不准备预测哪个会更快。

一旦代码被JIT编译,我自信地预测两个不同版本的代码之间将存在/将没有性能差异。我预测JIT编译器将生成具有相同速度的代码。 (任何针对此的JIT编译器优化都会在很久以前实现,因为几乎每次构造对象时都会链接到Object<init>。)


在源代码级别,接受的智慧是构造函数中的super()调用对性能没有任何影响,无论超类是什么。同样,如果您明确写入extends Object,则性能差异为零。

任何注释的唯一区别在于可读性。这纯粹是代码风格问题。


1 - 您没有提供任何可靠的证据。见评论。