W / dalvikvm:VFY:invoke类型与方法类型不匹配

时间:2014-09-03 08:15:26

标签: java android

我经常遇到这个错误...尤其是在访问某个类的私有方法时...真的不知道这是什么...我也无法从Google那里找到太多解释。

我发布了一个导致例外的示例:

我有一个SyncAdapter,这是导致崩溃的onPerformSync方法..

    @Override
    @SuppressLint("NewApi")
    public void onPerformSync(Account account, Bundle extras, String authority,
                              ContentProviderClient provider, SyncResult syncResult) {
        // some code...

        HmacSHA224 mac = new HmacSHA224(accessToken.getBytes());
        JSONArray entries = new JSONArray();
        JSONArray hashes = null;
        String lastName = null;

        // some other code
    }

HmacSHA224是我定义的自定义类:

public class HmacSHA224 {

private SHA224 mMessageDigest;
private byte[] mKey;

public HmacSHA224(byte[] key) {
    mMessageDigest = new SHA224();
    mKey = key;
}

public byte[] hash(byte[] message) {
    int blockSize = 64;
    int digestSize = 28;
    if (mKey.length > blockSize) {
        mKey = mMessageDigest.digest(mKey);
    }

    if (mKey.length < blockSize) {
        byte[] k = new byte[blockSize];
        System.arraycopy(mKey, 0, k, 0, mKey.length);
        mKey = k;
    }

    byte[] o = new byte[blockSize + digestSize];
    byte[] i = new byte[blockSize + message.length];
    for (int n = 0; n < blockSize; n++) {
        o[n] = (byte)(mKey[n] ^ 0x5c);
        i[n] = (byte)(mKey[n] ^ 0x36);
    }

    System.arraycopy(message, 0, i, blockSize, message.length);
    System.arraycopy(mMessageDigest.digest(i), 0, o, blockSize, digestSize);

    return mMessageDigest.digest(o);
}

}

和SHA224课程:

public final class SHA224 extends MessageDigestSpi {

    private static int[] H = { some values };

    private static int[] K = { some values };

    private ByteBuffer dataBuf = ByteBuffer.allocate(64);
    private int length = 0;
    private int[] h = H.clone();

    private void processChunk() {
        dataBuf.rewind();
        int[] w = new int[64];
        for (int i = 0; i < 16; i++)
            w[i] = dataBuf.getInt();
        dataBuf.clear();

        for (int i = 16; i < 64; i++) {
            int s0 = w[i - 15];
            s0 = ((s0 >>> 7) | (s0 << 25)) ^ ((s0 >>> 18) | (s0 << 14)) ^ (s0 >>> 3);
            int s1 = w[i - 2];
            s1 = ((s1 >>> 17) | (s1 << 15)) ^ ((s1 >>> 19) | (s1 << 13)) ^ (s1 >>> 10);
            w[i] = w[i - 16] + s0 + w[i - 7] + s1;
        }

        int a = this.h[0], b = this.h[1], c = this.h[2], d = this.h[3],
                e = this.h[4], f = this.h[5], g = this.h[6], h = this.h[7];

        for (int i = 0; i < 64; i++) {
            int s0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));
            int maj = (a & b) ^ (a & c) ^ (b & c);
            int t2 = s0 + maj;
            int s1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));
            int ch = (e & f) ^ ((~e) & g);
            int t1 = h + s1 + ch + K[i] + w[i];

            h = g;
            g = f;
            f = e;
            e = d + t1;
            d = c;
            c = b;
            b = a;
            a = t1 + t2;
        }

        this.h[0] += a;
        this.h[1] += b;
        this.h[2] += c;
        this.h[3] += d;
        this.h[4] += e;
        this.h[5] += f;
        this.h[6] += g;
        this.h[7] += h;
    }

    @Override
    protected byte[] engineDigest() {
        long bitLength = length * 8L;
        engineUpdate((byte) 0x80);
        for (; (length + 8) % 64 != 0;)
            engineUpdate((byte) 0);
        dataBuf.putLong(bitLength);
        processChunk();

        ByteBuffer result = ByteBuffer.allocate(28);
        for (int i = 0; i < 7; i++)
            result.putInt(h[i]);

        engineReset();
        return result.array();
    }

    @Override
    protected void engineReset() {
        dataBuf.clear();
        length = 0;
        h = H.clone();
    }

    @Override
    protected void engineUpdate(byte src) {
        dataBuf.put(src);
        length += 1;
        if (length % 64 == 0)
            processChunk();
    }

    @Override
    protected void engineUpdate(byte[] src, int offset, int count) {
        for (int i = offset; i < offset + count; i++)
            engineUpdate(src[i]);
    }

    public byte[] digest(byte[] input) {
        engineUpdate(input, 0, input.length);
        return engineDigest();
    }

}

我发现崩溃发生在我启动mac值时..错误跟踪进入

  

VFY:拒绝Lim / com / example / utils / SHA224; .engineDigest()

更新:

我有以下日志:

09-03 14:38:59.841  25084-25134/com.example.android:sync W/dalvikvm﹕ VFY: invoke type does not match method type of Lcom/example/android/utils/SHA224;.processChunk
09-03 14:38:59.841  25084-25134/com.example.android:sync W/dalvikvm﹕ VFY:  rejecting opcode 0x6f at 0x002b
09-03 14:38:59.841  25084-25134/com.example.android:sync W/dalvikvm﹕ VFY:  rejected Lcom/example/android/utils/SHA224;.engineDigest ()[B
09-03 14:38:59.841  25084-25134/com.example.android:sync W/dalvikvm﹕ Verifier rejected class Lcom/example/android/utils/SHA224;
09-03 14:38:59.841  25084-25134/com.example.android:sync W/dalvikvm﹕ threadid=23: thread exiting with uncaught exception (group=0x415daba8)
09-03 14:38:59.841  25084-25134/com.example.android:sync W/System.err﹕ java.lang.VerifyError: com/example/android/utils/SHA224
09-03 14:38:59.841  25084-25134/com.example.android:sync W/System.err﹕ at com.example.android.utils.HmacSHA224.<init>(HmacSHA224.java:5)
09-03 14:38:59.841  25084-25134/com.example.android:sync W/System.err﹕ at com.example.android.adapters.SyncAdapter.onPerformSync(SyncAdapter.java:71)
09-03 14:38:59.841  25084-25134/com.example.android:sync W/System.err﹕ at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:259)
09-03 14:38:59.851  25084-25134/com.example.android:sync E/AndroidRuntime﹕ FATAL EXCEPTION: SyncAdapterThread-1
    Process: com.example.android:sync, PID: 25084
    java.lang.VerifyError: com/example/android/utils/SHA224
            at com.example.android.utils.HmacSHA224.<init>(HmacSHA224.java:5)
            at com.example.android.adapters.SyncAdapter.onPerformSync(SyncAdapter.java:71)
            at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:259)

再次更新 所以问题出在processChunk()方法中,当更改为protected(而不是private)时,崩溃消失了。但!!!我想知道它为什么会这样。为什么我不能将某些方法保密并在同一个类中调用...

2 个答案:

答案 0 :(得分:1)

对于为什么会发生这种情况并不是一个明确的答案,但这是我对发生的事情和调查方向的分析:

日志说的是,类SHA224的字节码验证在尝试将其加载到VM内存时失败了:

Verifier rejected class Lcom/example/android/utils/SHA224;

详细信息告诉我们,由于对processChunk()的父类实现的调用,验证失败,MessageDigestSpi父类中不存在:

VFY: invoke type does not match method type of Lcom/example/android/utils/SHA224;.processChunk
  VFY:  rejecting opcode 0x6f at 0x002b
  VFY:  rejected Lcom/example/android/utils/SHA224;.engineDigest ()[B

(操作码0x6F用于调用超级方法on Dalvik

所以看起来代码中对processChunk()的调用被编译为super.processChunk(),这在加载时自然无法解决。为什么,我不能说,它可能是构建工具链中的一个错误,特别是因为您只是将processChunk()方法范围更改为protected正确编译它。

进一步调查的事项:

  • 尝试调用this.processChunk()而不是processChunk()(应该是相同但会暗示编译器问题)
  • 尝试使用最新的构建工具针对稳定的API版本(例如19)进行编译,并在稳定的Android运行时(例如4.4)上运行

我在我的环境中尝试了您的代码(SDK工具23.0.2,平台工具20,目标最小API 8,在4.4 / Dalvik上运行)并且我没有遇到此问题,即使使用摘要代码也是如此放入在单独进程中运行的同步适配器。 所以我肯定会检查你的建筑环境。


这不能解决问题的根源,但是对于Android上的哈希,你宁可使用native API

MessageDigest sha224 = MessageDigest.getInstance("SHA-224");
// etc

虽然没有提供SHA-224哈希算法的设备会失败...

答案 1 :(得分:1)

对我而言,buildToolsVersion设置为19,compileSdkVersion设置为build.gradle中的21。所以我的建议是,尝试将buildToolsVersion更改为尽可能高的数字。