Java类文件上的ACC_SUPER访问标志的作用是什么?
创建新对象时,invokespecial
JVM指令用于调用初始化方法(<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