2014-09-03 44 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更改爲儘可能高的數字。