Java 铸造时不同级别的铸造性能
假设我们有三个(或更多)类 公共A类{} 公共类B扩展了{} 公共类C扩展B实现G{} 假设每个类都有自己的20个(或更多)方法 铸造到C与铸造到A对性能的影响更大吗?Java casting如何在引擎盖下工作 它是否必须在向下投射时通过反射检查所有方法和字段的存在 编辑: 类的大小(字段和方法的数量)是否会影响强制转换时的性能? 我对OpenJRE和Dalvik都感兴趣Java 铸造时不同级别的铸造性能,java,android,dalvik,Java,Android,Dalvik,假设我们有三个(或更多)类 公共A类{} 公共类B扩展了{} 公共类C扩展B实现G{} 假设每个类都有自己的20个(或更多)方法 铸造到C与铸造到A对性能的影响更大吗?Java casting如何在引擎盖下工作 它是否必须在向下投射时通过反射检查所有方法和字段的存在 编辑: 类的大小(字段和方法的数量)是否会影响强制转换时的性能? 我对OpenJRE和Dalvik都感兴趣 作为参考,我知道升级可以毫无问题地完成。转换的性能取决于JVM实现 仅确定强制转换的需求(包括递归算法),但不设置任何实现需
作为参考,我知道升级可以毫无问题地完成。转换的性能取决于JVM实现 仅确定强制转换的需求(包括递归算法),但不设置任何实现需求。事实上,它们也是以同样的方式确定的。所有产生与所提出算法相同结果的JVM实现都被视为适当的JVM
通常,向下转换到
C
会花费更多的时间,因为JVM必须检查对象的运行时类型。向上转换到A
时,没有理由执行相同的检查,因为B
扩展A
实际上,JVM并不关心方法和字段的数量。它只比较类型层次结构,与您可以使用反射检查的相同(o.getClass()
)
我制作了一个示例代码,如下所示,一个向下投射,然后一个向上投射:
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
0新java.lang.Integer[16]
3次重复
4 iconst_1有关HotSpot中的checkcast
的详细体系结构(在其他响应中提到了作为向下广播的JVM机制),请参阅本会议论文:
摘自摘要的一段话:
在实际的基准测试运行中,我们的技术执行完整的子类型
检入3条指令(仅1条内存引用)基本上所有
时间在极少数情况下,它会恢复为较慢的阵列扫描。记忆
使用量适中(每堂课6个单词),可以用时间来交换
因此,如果不使用大量强制转换编写一些非常低级的代码,其影响可以忽略不计。“因为JVM必须检查对象的运行时类型”它是如何检查的?实际上,我错了,事实甚至比isAssignableFrom()
更为自然。因此,如果您对检查强制转换的内部结构感到好奇,也许试着用谷歌搜索一下(我找不到任何相关的结果)。我假设搜索是通过casted对象运行时类的类型层次结构(扩展和实现)完成的。区别可能是一些处理器周期,但由于它是本机代码,我认为这与此无关。check cast
调用dvmInstanceOf()
,它执行缓存查找。上次我检查框架代码的命中率>95%。因此,在大多数情况下,课程深度的影响并不明显,只是来源。从dalvik/vm/mterp/c/OP\u CHECK\u CAST.cpp
开始查看它的起始位置。在dalvik/vm/oo/TypeCheck.cpp
中签入dvminstanceofnontrival()
的缓存通过一些宏功能实现;请参见dalvik/vm/AtomicCache.h
和.cpp
。如果未命中,则将进入isInstanceof()
,然后根据检查的是接口、数组还是类,将其拆分。对于接口,它在接口的“展平”列表中进行线性遍历;对于类,它在树上进行递归遍历。