Java类文件上的ACC_SUPER访问标志的作用是什么?

创建新对象时,invokespecialJVM指令用于调用初始化方法(<init>)。该指令的描述表明(但未阐明)是决定调用超类的构造函数还是当前类的构造函数取决于文件中ACC_SUPER标志设置的状态class

根据Sun JVM规范:

接下来,除非满足以下所有条件,否则将选择已解析的方法进行调用:

  • 为当前类设置ACC_SUPER标志(请参见表4.1,“类访问和属性修饰符”)。

-

源(invokespecial操作码定义)

ACC_SUPER标志的设置指示Java虚拟机要表达其调用特殊指令的两种替代语义中的哪一种。ACC_SUPER标志的存在是为了向后兼容Sun较早的编译器为Java编程语言编译的代码。Java虚拟机的所有新实现都应实现本规范中记录的invokeinspecial的语义。Java虚拟机指令集的所有新编译器都应设置ACC_SUPER标志。Sun的较早版本的编译器会生成未设置ACC_SUPER的ClassFile标志。Sun的较早Java虚拟机实现将忽略该标志(如果已设置)。

-

来源(ClassFile格式)

该定义指出该标志是为了与旧编译器向后兼容。但是它继续与Sun's older Java virtual machine implementations

ignore the flag if it is set.

该标志是否仍与invokespecial操作码一起使用?据我所知,它似乎没有任何目的,我也找不到资源可以证明它曾经做到过。

谢谢。

回答:

引入了ACC_SUPER来纠正超级方法的调用问题。ACC_SUPER标志将一个类标记为针对操作码183指令的更改的语义进行编译。它的用途类似于类文件版本号,因为它允许JVM检测是否为该指令的旧语义或新语义编译了一个类。Java

1.0.2未设置并忽略ACC_SUPER,而Java 1.1及更高版本始终设置ACC_SUPER。

Java

1.1的操作码183,现在被称为字节码指令之前invokespecial被称为invokenonvirtual并且有部分不同的规格。每当必须调用实例方法而不进行虚拟方法查找时都使用它。私有方法,实例初始化器(构造函数)以及在上实现方法调用就是这种情况super。但是后一种情况导致了类库的发展。

字节码(CONSTANT_Methodref_info)中的方法引用不仅定义了方法的名称,参数和返回类型,还定义了该方法所属的类。操作码183获得了这样的方法引用参数,旨在直接从指定的类调用引用的方法,而无需进一步查找。在调用的情况下,super编译器负责解析实现该方法的最接近的超类,并生成对该字节的引用。

从Java

1.1开始,已对其进行了更改,以实质上忽略所引用的类CONSTANT_Methodref_info,而改为在JVM中使用给定的方法名称和签名查找最接近的super方法。现在通常在加载类时执行此操作,或者恰好在执行指令或第一次编译JIT之前执行此操作。

这是为什么需要进行此更改的示例。在Java 1.0.2中,AWT类的Container和Component是这样定义的:

class Component

{

public void paint( Graphics g ) {}

}

class Container extends Component

{

// inherits paint from Component but doesn't override it

}

在Java 1.1中,将类Conatiner更改为具有自己的实现paint

class Container extends Component

{

public void paint( Graphics g ) {/*...*/}

}

现在,当您有一个直接或间接的Container子类进行调用super.paint(g)并针对1.0.2进行编译时,它会生成一条invokenonvirtual指令,Component.paint因为这是第一个具有此方法的父级。但是,如果您在也有Container.paint它的JVM上使用此已编译的类,则仍然会调用Component.paint它,这不是您期望的。

另一方面,当您为1.1编译该类并在1.0.2

JVM上执行该类时,它将抛出AbstractMethodError或更可能使该时代的VM崩溃。为避免崩溃,您必须((Component)super).paint(g)使用1.1编译器进行编写和编译,以在任一VM中获得所需的行为。这将设置ACC_SUPER,但仍生成要调用的指令Component.paint。1.0.2虚拟机将忽略ACC_SUPER并直接进行调用Component.paint,而1.1虚拟机将找到ACC_SUPER集,并进行查找本身(Container.paint即使字节码方法引用为)也将使其调用Component.paint

您可以在ikvm.net

Weblog上的旧文章中找到有关此内容的更多信息。

以上是 Java类文件上的ACC_SUPER访问标志的作用是什么? 的全部内容, 来源链接: utcz.com/qa/427517.html

回到顶部