Oracle JVM:调用特殊指令
Oracle JVM: invokespecial instruction
我对下面的段落感到困惑(来源 Oracle JVM specification for invokespecial instruction)。
If all of the following are true, let C be the direct superclass of
the current class:
- The resolved method is not an instance initialization method (§2.9).
- If the symbolic reference names a class (not an interface), then that class is a superclass of the current class.
- The ACC_SUPER flag is set for the class file (§4.1).
我在invokespecial指令描述的第一段做了一些标签(表示法://label//)。我在下面的问题中使用了这个标签。
The unsigned indexbyte1 and indexbyte2 are used to construct an index
into the run-time constant pool of the current class //current class// (§2.6), where the
value of the index is (indexbyte1 << 8) | indexbyte2. The run-time
constant pool item at that index must be a symbolic reference to a
method or an interface method (§5.1), which gives the name //method name// and
descriptor //method descriptor// (§4.3.3) of the method as well as a symbolic reference to
the class //referenced class// or interface in which the method is to be found. The named
method is resolved //resolved method// (§5.4.3.3, §5.4.3.4).
根据标签,我现在检查带有条件的段落。
- The resolved method is not an instance initialization method (§2.9).
问题 1:因此,我检查 //方法名称// 是否不等于“”或“”,对吧?
- If the symbolic reference names a class (not an interface), then that class is a superclass of the current class.
问题2:这是什么意思? //引用的class//必须是直接或非直接superclass(superclass of superclass等) of //current class//?
- The ACC_SUPER flag is set for the class file (§4.1).
问题 3: Class 文件属于哪个 class? //引用class//?
- The resolved method is not an instance initialization method (§2.9).
所以,我检查 //方法名称// 是否不等于“”或“”,对吗?
正确。嗯,更准确的说“不是实例初始化方法”只是指方法名不是<init>
。但是由于调用名为 <clinit>
的方法在一般情况下 是被禁止的 ,因此得出方法名称必须既不是 <init>
也不是 <clinit>
的结论是正确的。
- If the symbolic reference names a class (not an interface), then that class is a superclass of the current class.
这是什么意思? //引用的class//必须是直接或非直接superclass(superclass of superclass等) of //current class//?
是的,如果引用的class不是一个接口,它一定是当前class的一个superclass。请注意,这是一个条件,它暗示在枚举之前声明“让 C 成为当前 class 的直接超class”。更多信息,请参见下文。
还值得注意的是,对于非接口目标类型,目标类型必须表示当前 class 或当前 class 的超 class 定义在 4.9.2. Structural Constraints.
- The ACC_SUPER flag is set for the class file (§4.1).
Class 文件 class? //引用class//?
当前class的class文件,即包含invokespecial
指令的class。请注意,这是事实上不存在的要求。关注 link to §4.1:
时您会注意到
The ACC_SUPER
flag indicates which of two alternative semantics is to be expressed by the invokespecial instruction (§invokespecial) if it appears in this class or interface. Compilers to the instruction set of the Java Virtual Machine should set the ACC_SUPER
flag. In Java SE 8 and above, the Java Virtual Machine considers the ACC_SUPER
flag to be set in every class
file, regardless of the actual value of the flag in the class
file and the version of the class
file.
The ACC_SUPER
flag exists for backward compatibility with code compiled by older compilers for the Java programming language. In JDK releases prior to 1.0.2, the compiler generated access_flags
in which the flag now representing ACC_SUPER
had no assigned meaning, and Oracle's Java Virtual Machine implementation ignored the flag if it was set.
所以当JVM“考虑在每个class
文件中设置ACC_SUPER
标志时,必须设置标志的要求不需要检查…
历史方面也说明了上面的意思。 invokespecial
指令用于实现 super.methodName(…)
调用。在早期的 1.0 实现中,编译器解析包含方法声明的目标 class 并且 JVM 调用该方法,忽略任何覆盖方法。这产生了两个问题。首先,恶意代码可以通过使用指向该方法超类型的适当 invokespecial
指令来绕过类型层次结构中的覆盖方法。此外,它创建了对超级 class 层次结构的依赖性,限制了可能的更改。
当前规则是编译器总是将 super.methodName(…)
编码为包含该调用的 class 的直接 superclass,而不管 super[=84 中的哪个位置=] hierarchy 已在编译时 找到实际声明 。在运行时,当 JVM 遇到这样的 invokespecial
指令时,它将在超类型层次结构中搜索最具体的方法,并尊重其中的任何覆盖。这确保了在一个 class 中,将只依赖于它的直接 superclass (除非代码中有其他对更抽象类型的显式引用)并且它允许重构,比如向上移动方法或在不影响兼容性的情况下降低类型层次结构。
枚举条件的字面意思是引用的class可能是任意superclass(标准编译器只生成class文件使用直接superclass) 以满足直接 superclass 将在任何情况下用于解析该方法的条件。这包括执行为 1.0.2 之前的 Java 1.0 编译的 class 文件时的情况,现在忽略 ACC_SUPER
的缺失。非接口类型支持的唯一其他情况是目标类型与当前 class 完全匹配的情况,用于调用 private
方法。
引入 ACC_FLAG
是为了向后兼容。它的存在表示应该使用新行为,但如上所述,最近的 JVM 仅支持“新”行为,这是二十年来最先进的。
我对下面的段落感到困惑(来源 Oracle JVM specification for invokespecial instruction)。
If all of the following are true, let C be the direct superclass of the current class:
- The resolved method is not an instance initialization method (§2.9).
- If the symbolic reference names a class (not an interface), then that class is a superclass of the current class.
- The ACC_SUPER flag is set for the class file (§4.1).
我在invokespecial指令描述的第一段做了一些标签(表示法://label//)。我在下面的问题中使用了这个标签。
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class //current class// (§2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool item at that index must be a symbolic reference to a method or an interface method (§5.1), which gives the name //method name// and descriptor //method descriptor// (§4.3.3) of the method as well as a symbolic reference to the class //referenced class// or interface in which the method is to be found. The named method is resolved //resolved method// (§5.4.3.3, §5.4.3.4).
根据标签,我现在检查带有条件的段落。
- The resolved method is not an instance initialization method (§2.9).
问题 1:因此,我检查 //方法名称// 是否不等于“
- If the symbolic reference names a class (not an interface), then that class is a superclass of the current class.
问题2:这是什么意思? //引用的class//必须是直接或非直接superclass(superclass of superclass等) of //current class//?
- The ACC_SUPER flag is set for the class file (§4.1).
问题 3: Class 文件属于哪个 class? //引用class//?
- The resolved method is not an instance initialization method (§2.9).
所以,我检查 //方法名称// 是否不等于“
”或“ ”,对吗?
正确。嗯,更准确的说“不是实例初始化方法”只是指方法名不是<init>
。但是由于调用名为 <clinit>
的方法在一般情况下 是被禁止的 ,因此得出方法名称必须既不是 <init>
也不是 <clinit>
的结论是正确的。
- If the symbolic reference names a class (not an interface), then that class is a superclass of the current class.
这是什么意思? //引用的class//必须是直接或非直接superclass(superclass of superclass等) of //current class//?
是的,如果引用的class不是一个接口,它一定是当前class的一个superclass。请注意,这是一个条件,它暗示在枚举之前声明“让 C 成为当前 class 的直接超class”。更多信息,请参见下文。
还值得注意的是,对于非接口目标类型,目标类型必须表示当前 class 或当前 class 的超 class 定义在 4.9.2. Structural Constraints.
- The ACC_SUPER flag is set for the class file (§4.1).
Class 文件 class? //引用class//?
当前class的class文件,即包含invokespecial
指令的class。请注意,这是事实上不存在的要求。关注 link to §4.1:
The
ACC_SUPER
flag indicates which of two alternative semantics is to be expressed by the invokespecial instruction (§invokespecial) if it appears in this class or interface. Compilers to the instruction set of the Java Virtual Machine should set theACC_SUPER
flag. In Java SE 8 and above, the Java Virtual Machine considers theACC_SUPER
flag to be set in everyclass
file, regardless of the actual value of the flag in theclass
file and the version of theclass
file.The
ACC_SUPER
flag exists for backward compatibility with code compiled by older compilers for the Java programming language. In JDK releases prior to 1.0.2, the compiler generatedaccess_flags
in which the flag now representingACC_SUPER
had no assigned meaning, and Oracle's Java Virtual Machine implementation ignored the flag if it was set.
所以当JVM“考虑在每个class
文件中设置ACC_SUPER
标志时,必须设置标志的要求不需要检查…
历史方面也说明了上面的意思。 invokespecial
指令用于实现 super.methodName(…)
调用。在早期的 1.0 实现中,编译器解析包含方法声明的目标 class 并且 JVM 调用该方法,忽略任何覆盖方法。这产生了两个问题。首先,恶意代码可以通过使用指向该方法超类型的适当 invokespecial
指令来绕过类型层次结构中的覆盖方法。此外,它创建了对超级 class 层次结构的依赖性,限制了可能的更改。
当前规则是编译器总是将 super.methodName(…)
编码为包含该调用的 class 的直接 superclass,而不管 super[=84 中的哪个位置=] hierarchy 已在编译时 找到实际声明 。在运行时,当 JVM 遇到这样的 invokespecial
指令时,它将在超类型层次结构中搜索最具体的方法,并尊重其中的任何覆盖。这确保了在一个 class 中,将只依赖于它的直接 superclass (除非代码中有其他对更抽象类型的显式引用)并且它允许重构,比如向上移动方法或在不影响兼容性的情况下降低类型层次结构。
枚举条件的字面意思是引用的class可能是任意superclass(标准编译器只生成class文件使用直接superclass) 以满足直接 superclass 将在任何情况下用于解析该方法的条件。这包括执行为 1.0.2 之前的 Java 1.0 编译的 class 文件时的情况,现在忽略 ACC_SUPER
的缺失。非接口类型支持的唯一其他情况是目标类型与当前 class 完全匹配的情况,用于调用 private
方法。
引入 ACC_FLAG
是为了向后兼容。它的存在表示应该使用新行为,但如上所述,最近的 JVM 仅支持“新”行为,这是二十年来最先进的。