是什么导致Android Dalvik java.lang.VerifyError"数组索引的无效的reg类型"?

str*_*r4d 2 java android dalvik

我最近升级了用于构建应用程序的Android构建工具,从19.1.0到21.0.2.该应用程序编译,但当我启动它时,我收到此错误:

net.i2p.android W/dalvikvm? Invalid reg type for array index (1103759864)
net.i2p.android W/dalvikvm? VFY:  rejected Lnet/i2p/crypto/eddsa/math/ed25519/Ed25519FieldElement;.multiply (Lnet/i2p/crypto/eddsa/math/FieldElement;)Lnet/i2p/crypto/eddsa/math/FieldElement;
net.i2p.android W/dalvikvm? VFY:  rejecting opcode 0x44 at 0x001c
net.i2p.android W/dalvikvm? VFY:  rejected Lnet/i2p/crypto/eddsa/math/ed25519/Ed25519FieldElement;.multiply (Lnet/i2p/crypto/eddsa/math/FieldElement;)Lnet/i2p/crypto/eddsa/math/FieldElement;
net.i2p.android W/dalvikvm? Verifier rejected class Lnet/i2p/crypto/eddsa/math/ed25519/Ed25519FieldElement;
net.i2p.android W/dalvikvm? Exception Ljava/lang/VerifyError; thrown while initializing Lnet/i2p/crypto/eddsa/spec/EdDSANamedCurveTable;
net.i2p.android W/dalvikvm? Exception Ljava/lang/VerifyError; thrown while initializing Lnet/i2p/crypto/SigType;
net.i2p.android W/dalvikvm? Exception Ljava/lang/VerifyError; thrown while initializing Lnet/i2p/router/startup/CreateRouterInfoJob;
net.i2p.android W/dalvikvm? threadid=12: thread exiting with uncaught exception (group=0x41caeda0)
net.i2p.android E/AndroidRuntime? FATAL EXCEPTION: Thread-6713
    Process: net.i2p.android, PID: 26198
    java.lang.VerifyError: net/i2p/crypto/eddsa/math/ed25519/Ed25519FieldElement
            at net.i2p.crypto.eddsa.math.ed25519.Ed25519LittleEndianEncoding.decode(Ed25519LittleEndianEncoding.java:189)
            at net.i2p.crypto.eddsa.math.Field.fromByteArray(Field.java:55)
            at net.i2p.crypto.eddsa.math.Field.<init>(Field.java:39)
            at net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable.<clinit>(EdDSANamedCurveTable.java:21)
            at net.i2p.crypto.SigType.<clinit>(SigType.java:51)
            at net.i2p.router.startup.CreateRouterInfoJob.<clinit>(CreateRouterInfoJob.java:54)
            at net.i2p.router.KeyManager$SynchronizeKeysJob.syncKeys(KeyManager.java:156)
            at net.i2p.router.KeyManager$SynchronizeKeysJob.runJob(KeyManager.java:146)
            at net.i2p.router.KeyManager.startup(KeyManager.java:65)
            at net.i2p.router.Router.runRouter(Router.java:468)
            at net.i2p.router.Router.main(Router.java:1158)
            at net.i2p.router.RouterLaunch.main(RouterLaunch.java:21)
            at net.i2p.android.router.service.RouterService$Starter.run(RouterService.java:320)
            at java.lang.Thread.run(Thread.java:841)
Run Code Online (Sandbox Code Playgroud)

我在同一设备上运行应用程序,并且没有更改任何代码.为什么Dalvik现在拒绝这个课程?我在网上搜索过,但没有发现任何关于错误的信息Invalid reg type for array index.

被拒绝的类的源代码在这里.

str*_*r4d 5

我无法找到解决问题的构建工具中的具体更改,但在查看了不同Dalvik问题的答案后,我发现了错误.

Dalvik拒绝,Ed25519FieldElement.multiply()因为它包含155个局部变量.此方法直接从相应的C代码移植,并且不能很好地转换为Java字节码.看起来在19.1.0和21.0之间.+,构建工具中的编译器以防止Dalvik处理这么多局部变量的方式进行了更改.

本页的最后一篇文章提供了一些额外的见解:

是的,Dalvik编译器试图为方法中的每个局部变量分配一个"寄存器".它应该能够处理那么多,但显然不能.通过使它们成为实例变量,您可以删除编译器"管理"它们的需要/愿望(并且还使该方法相当小).

我的解决方案是删除20个不必要的变量(像无操作分配一样g0 = g[0]),而是直接使用数组.这确实增加了未来bug进入代码的可能性(如果其中一个数组索引被意外更改),但是将局部变量的数量减少到135则解决了运行时类拒绝问题.

"正确"的解决方案是完全重构该方法以减少其长度.必须小心这一点,以避免引入旁道攻击向量.