Android中Dalvik检查和优化.apk/.jar的流程introduce(2)

执行verification成功的类在ODEX文件中有一个flag set,当它们被加载时,就不会再进行verification。linux系统的安全机制会防止这个文件被破坏,但如果你能绕过去,还是能去破坏它的。ODEX文件有一个32-bit的checksum,但只能做一个快速检查。

Optimization

VM解释器在第一次运行一段代码时会做一些optimization。比如,把常量池引用替换成指向内部数据结构的指针,一些永远成功的操作或固定的代码被替换成更简单的形式。做这些optimization需要的信息有的只能在运行时得到,有的可以推断出来。

dalvik做的optimization包含下面这些:

1、对于虚方法的调用,把方法索引修改成vtable索引。

2、把field的get/put修改成字节偏移量。把boolean/byte/char/short等类型的变量合并到一个32-bit的形式,更少的代码可以更有效地利用CPU的I-cache。

3、把一些大量使用的简单方法进行inline,比如String.length()。这样能减少方法调用的开销。

4、删除空方法。

5、加入一些计算好的数据。比如,VM需要一个hash table来查找类名字,我们就可以在Optimization阶段进行计算,不用放到DEX加载的时候了。

所有的指令修改都是使用一个Dalvik标准没有定义的指令去替换原有指令。这样,我们就可以让优化和没有优化的指令自由搭配。具体的操作与VM版本有关。

Optimization过程有两个地方需要我们注意:

1、VM如果更新的话,vtable索引和字节偏移量可能会更新。

2、如果两个DEX互相信赖,而其中一个DEX更新的话,确保优化后的索引和偏移量有效。

Dependencies and Limitations

优化后的DEX会包含一个它信赖的DEX文件列表,并添加了CRC-32和修改时间。文件列表中包含了dalvik-cache目录下的文件的路径和相应的SHA-1签名。而文件在设备上的timestamp不可信也不能用。另外还有VM版本号。

如果当前DEX所依赖的DEX有更新,我们也需要更新当前DEX。如果我们可以做一个JIT的dexopt调用,更新过程很easy。但如果只能依赖installer daemon,或者这个DEX被装到ODEX中的话,VM只能拒绝它了。

dexopt的输出与平台版本,VM版本有关,想编写一个运行在PC上,而优化后的输出在其它设备使用的dexopt很难。因此,dexopt是在目标设备上或者目标设备的模拟器上运行。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwwgjf.html