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

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

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.(Field.java:39) at net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable.(EdDSANamedCurveTable.java:21) at net.i2p.crypto.SigType.(SigType.java:51) at net.i2p.router.startup.CreateRouterInfoJob.(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) 

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

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

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

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

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

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

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

“正确”的解决方案是完全重构该方法以减少其长度。 这必须小心,以避免引入侧通道攻击向量 。