我正在研究一些android性能问题,并注意到dex代码中的一些次优模式。我只是想知道是否有人知道这是意料之中的事,以及背后的理由是什么。
例如,考虑下面的Java代码:
m_testField += i;
doSomething(m_testField);
当这是建立,然后运行巴克斯马利,它看起来像如下:
iget v1, p0, Lcom/example/MainActivity$FieldTest;->m_testField:I
add-int/2addr v1, v0
iput v1, p0, Lcom/example/MainActivity$FieldTest;->m_testField:I
iget v1, p0, Lcom/example/MainActivity$FieldTest;->m_testField:I
invoke-direct {p0, v1}, Lcom/example/MainActivity$FieldTest;->doSomething(I)V
关于我的部分是iget操作码,它将实例字段的值读入寄存器v1。同一个字段是从前面操作码中的同一个v1寄存器写入的,因此操作码看起来是完全冗余的。
我唯一能想到的是,这样做是为了使这个线程更安全。但这肯定是程序员的责任(通过使用同步块),而不是编译器的责任。虽然我还不确定100%,但我认为上面的行为与大多数C/C++编译器所做的完全不同。
我应该说,当使用proguard时,基本上产生相同的dex。我还应该提到,我使用的是最新的android工具和最新的jdk。
最佳答案
对字段的每个访问都是独立的。要获得所描述的行为,需要添加额外的局部变量:
int local = m_testField; // iget
local = local + i;
m_testField = local; // iput
doSomething(local);
也就是说,解释器、即时编译器和提前编译器的某些组合最终可能会在运行时为您进行这些优化。