2014-09-03 62 views
2

我遇到这个错误相当频繁方法类型...访问类的私有方法尤其是当......真不知道这是怎么回事?无论是我能找到谷歌太多的解释..W/dalvikvm:VFY:调用类型不匹配的

我只是张贴导致此异常的例子:

我有一个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:驳回林/com/example/utils/SHA224;.engineDigest()

UPDATE:

我有以下日志:

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()方法,当改为保护(而不是私人)崩溃消失。但!!!我想知道为什么它的行为这样。为什么我不能保留一些方法私人和同一个类中调用...

+0

你可以发表一些关于你所看到的错误的更多信息(stacktrace的复制粘贴会很好)以及你的'SHA224'类的构造函数吗? 您是在给定设备上自己遇到过这个问题的,还是仅在远程聚合日志(如Google Play控制台)中看到过它? – desseim 2014-09-03 08:34:47

+0

@desseim请看看添加的日志。 SHA224来自Android,而不是我的代码。我不是远程地在设备上遇到这个问题谢谢您的帮助! – xialin 2014-09-03 08:46:05

+0

Android API中没有'SHA224'类,如果你看看堆栈消息,你会看到它在'com.example.android.utils'包中,它与你的'HmacSHA224'类是相同的包。 我相信'SHA224'类实例的初始化有问题。 – desseim 2014-09-03 09:07:24

回答

1

不上为什么出现这种情况还没有一个明确的答案,但这里是我发生了什么的分析,方向调查:

什么日志说是类SHA224的字节码验证,而试图将其加载到虚拟内存中,失败:

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

的细节告诉我们,在验证失败,因为调用中不存在的父类实现父类:

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失败哈希算法虽然...

+0

哇!尊重!我以前没有时间进一步调查。立刻提出您的建议,并尝试您的建议,并在明天回复您!非常感谢你的帮助。 – xialin 2014-09-03 17:19:10

1

对我来说,它是在buildToolsVersion设置为19和compileSdkVersion设置为21在build.gradle。所以我的建议是,尽量将您的buildToolsVersion更改为尽可能高的数字。