是什么原因导致Android Dalvik java.lang.VerifyError“数组索引的无效注册表类型”?

我最近将用于构建应用程序的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)

我在同一设备上运行该应用程序,但未更改任何代码.为什么达尔维克现在拒绝此类课程?我已经在线搜索过,但是没有发现有关数组索引错误的无效注册表类型的任何信息.

被拒绝类的源代码是here.

解决方法:

我无法在构建工具中找到能解决问题的具体更改,但查看the answer to a different Dalvik problem后,我发现了错误.

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

关于this page的最新文章提供了其他一些见解:

Yep, the Dalvik compiler attempts to assign a “register” to every
local variable in the method. It should be able to handle that many,
but apparently can’t. By making them instance variables you remove
the compiler’s need/desire to “manage” them (and also make the method
a fair amount smaller).

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

“正确”的解决方案是完全重构该方法以减少其长度.必须谨慎进行,以避免introducing side-channel attack vectors.

上一篇:java – Gradle构建失败:Dex文件不能超过64k


下一篇:java – 如何检查Dalvik Cache是​​否被修改