【问题标题】:Casting performance in different levels when casting down铸造时不同等级的铸造性能
【发布时间】:2013-05-24 18:21:51
【问题描述】:

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

公共类 A {}

公共类 B 扩展 A {}

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

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

转换为 C 与转换为 A 对性能的影响更大吗? Java 强制转换在底层是如何工作的?

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

编辑: 类的大小(字段和方法的数量)是否会影响转换时的性能? 我对 OpenJREDalvik 都感兴趣。

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

【问题讨论】:

    标签: java android dalvik


    【解决方案1】:

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

    JLS 5.5 仅确定强制转换的要求(包括递归算法),但没有对实现设置任何要求。实际上runtime cast rules in 5.5.3 也是以同样的方式确定的。所有产生与建议算法相同结果的 JVM 实现都被接受为适当的 JVM。

    一般来说,向下转换到C 需要更多时间,因为 JVM 必须检查对象的运行时类型。当投射到A 时,没有理由做同样的检查,因为B 扩展了A

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

    我做了一个示例代码如下,一个downcast,然后一个upcast:

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

    编译后的字节码如下:

     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
    

    因此,有一条特定的 JVM 指令可以检查堆栈顶部的元素是否具有给定的类。

    使用 upcast,根本没有检查。

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

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

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

    【讨论】:

    • "既然JVM必须检查对象的运行时类型"它是怎么检查的?
    • 其实我错了,真相比isAssignableFrom()更原生
    • 所以,如果您对check-cast 内部结构感到好奇,不妨尝试谷歌搜索(我找不到任何相关结果)。我想搜索是通过 casted object runtime class 向上的类型层次结构(扩展和实现)完成的。差异可能是一些处理器周期,但由于它是本机代码,我认为这无关紧要。
    • check-cast 调用 dvmInstanceOf(),它会进行缓存查找。上次我检查框架代码的命中率 > 95%。所以在大多数情况下,类深度的影响不会很明显。
    • 只是来源。从dalvik/vm/mterp/c/OP_CHECK_CAST.cpp 开始,看看它从哪里开始。在dalvik/vm/oo/TypeCheck.cpp 中签入dvmInstanceofNonTrivial() 的缓存是通过一些宏的乐趣实现的;见dalvik/vm/AtomicCache.h.cpp。如果它错过了,你最终会进入isInstanceof(),然后根据你检查的是接口、数组还是类而分裂出来。对于接口,它会线性遍历接口的“扁平化”列表,对于类,它会递归遍历树。
    【解决方案2】:

    有关 HotSpot 中checkcast 的详细架构(在其他回复中提到作为向下转换的 JVM 机制),请查看此会议论文:

    Fast subtype checking in the HotSpot JVM

    摘录:

    在实际的基准测试中,我们的技术执行完整的子类型 签入 3 条指令(仅 1 条内存引用),基本上所有 时间。在极少数情况下,它会恢复为较慢的阵列扫描。记忆 用法适中(每堂课 6 个单词),可以换取时间。

    因此,如果您不编写一些非常低级的代码并进行大量转换,则影响可以忽略不计。

    【讨论】:

      猜你喜欢
      • 2011-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多