Java 压缩开关和稀疏开关dalvik操作码之间的差异
我想知道dalvik中压缩交换机和稀疏交换机操作码之间的区别。请提供例子。谷歌提供的解释我不清楚Java 压缩开关和稀疏开关dalvik操作码之间的差异,java,android,bytecode,dalvik,dex,Java,Android,Bytecode,Dalvik,Dex,我想知道dalvik中压缩交换机和稀疏交换机操作码之间的区别。请提供例子。谷歌提供的解释我不清楚 谢谢。听起来好像压缩开关相当于Java的表开关,而稀疏开关相当于查找开关 packed开关使用一个简单的跳转表,以low+n的形式索引,其中low是案例标签中的最低测试值,n是开关的输入。每个索引处的值表示每个情况下的字节码偏移量。查找正确的跳转地址是一个固定时间操作 稀疏开关使用键-值对的排序列表,其中每个键都是来自大小写标签的测试值,值是跳转偏移量。为查找开关查找正确的跳转目标需要对键进行二
谢谢。听起来好像
压缩开关
相当于Java的表开关
,而稀疏开关
相当于查找开关
packed开关
使用一个简单的跳转表,以low+n
的形式索引,其中low
是案例
标签中的最低测试值,n
是开关的输入。每个索引处的值表示每个情况下的字节码偏移量。查找正确的跳转地址是一个固定时间操作
稀疏开关
使用键-值对的排序列表,其中每个键都是来自大小写
标签的测试值,值是跳转偏移量。为查找开关
查找正确的跳转目标需要对键进行二进制搜索,因此这是一个对数时间操作
编译器将选择使用哪个。如果键趋向于聚集或紧密地打包在一起,则可以有效地发出打包开关
(或者,用Java术语来说,表开关
)。但是如果键是稀疏的,并且值的范围(高-低+1
)很大,那么使用跳转表将需要一大块字节码,因为该范围内的所有值都必须存在于跳转表中,而不管是否有相应的大小写
标签。在这些场景中,编译器将发出一个稀疏开关
(查找开关
)
有趣的是,Dalvik工程师选择的命名方式描述了这些操作码应该用于的密钥分发,而Java工程师选择的命名方式描述了字节码操作数类似的概念数据结构
让我们看一些例子。考虑下面的java代码,它将产生<代码> TabLSwitCH (并且,当转换为Dalvik时,<代码>打包开关 >:
从概念上讲,压缩交换机
操作码的有效负载如下所示:
正如你所见,它相当紧凑。五个插槽中有三个指向实际的案例
目标,其余两个跳转到默认
目标。但是,如果我们的测试值更分散,会怎么样
static String sparseSwitch(final int n) {
switch (n) {
case 500:
return "Five Hundred";
case 300:
return "Three Hundred";
case 100:
return "One Hundred";
default:
return "Other";
}
}
如果编译器试图将其作为压缩开关发出
,则有效负载将如下所示:
请注意,几百个插槽中只有三个实际指向原始代码中的case
标签。剩下的只是为了填满跳转表。不是很节省空间,是吗?这就是为什么编译器会发出一个稀疏开关
,在这个特定示例中,它的字节码占用空间要小得多:
现在,这更合理了,你不觉得吗?然而,缺点是,我们不能根据输入准确地知道跳转到哪个索引,而是必须在表上执行二进制搜索,直到找到匹配的测试值。开关越大,对性能的影响越大,尽管其影响呈对数曲线。请参见此处
static String sparseSwitch(final int n) {
switch (n) {
case 500:
return "Five Hundred";
case 300:
return "Three Hundred";
case 100:
return "One Hundred";
default:
return "Other";
}
}