在击倒时铸造性能在不同的水平

Yar*_*lyk 5 java android dalvik

让我们假设我们有三个(或更多)类

公共课A {}

公共B级扩展A {}

公共类C扩展B实现G {}

假设每个类都有自己的20个(或更多)方法.

铸造到C与铸造到A对性能有更大的影响吗?Java编译如何在幕后工作?

在向下投射时,是否必须通过反射检查所有方法和字段是否存在?

编辑: 类的大小(字段和方法的数量)是否会在投射时影响性能?我对OpenJREDalvik感兴趣.

作为参考,我知道可以毫无问题地完成向上转换.

gab*_*sch 4

转换的性能取决于 JVM 实现。

JLS 5.5仅确定了铸造的要求(包括递归算法),但没有对实施提出任何要求。实际上5.5.3中的运行时转换规则也是以同样的方式确定的。所有产生与建议算法相同结果的 JVM 实现都被视为正确的 JVM。

通常,向下转换C需要花费更多时间,因为 JVM 必须检查对象的运行时类型。当投射到A它时,没有理由进行相同的检查,因为Bextends A

实际上,JVM并不关心方法和字段的数量。它仅比较类型层次结构,您可以使用反射检查相同的层次结构 ( o.getClass())

我制作了一个示例代码,如下所示,先是向下转型,然后是向上转型:

Object o = new Integer(1);
Integer i = (Integer) o;

Object o2 = i;
Run Code Online (Sandbox Code Playgroud)

编译后的字节码如下:

 0  new java.lang.Integer [16]
 3  dup
 4  iconst_1       <-- 1 as a parameter to the constructor
 5  invokespecial java.lang.Integer(int) [18]   <-- constructor
 8  astore_1 [o]       <-- store in 'o'
 9  aload_1 [o]
10  checkcast java.lang.Integer [16]    <-- DOWNCAST CHECK, SPECIAL BYTECODE
13  astore_2 [i]
14  aload_2 [i]
15  astore_3 [o2]   <-- WITH UPCAST NO CHECK
Run Code Online (Sandbox Code Playgroud)

因此,有一个特定的 JVM 指令用于检查给定类的堆栈顶部的元素。

对于 upcast,根本不需要检查。

类的大小(字段数、方法数、实际占用空间)并不重要,因为转换会检查Class(元数据,实际上是一个对象)。

层次结构级别的数量以及实现接口的数量(如果转换为接口)确实很重要,因为这是要检查的可遍历继承/实现树。

如果没有某种缓存用于此检查,我会感到惊讶。