2012-01-30 64 views
2

我們遇到了迄今爲​​止無法解決的錯誤,但沒有明顯的原因或解決方案。變更的最終屬性

在對包含從文件加載的數據的數組進行多次訪問時發生該錯誤。 ArrayIndexOutOfBounds發生在與此數組一起使用的代碼的各個部分中。

變量似乎隨機更改值。爲了防止這種情況,我們嘗試將修飾符「final」放入所有類屬性中。但他們仍然隨機改變價值。

下面,方法「執行()」及其內部循環「,而」它是發生錯誤的應用程序點。

public Set<Long> execute(InputStream datIn, int qtd) throws PersistenceException { 

     if (this.criterion == null) { 
      throw new PersistenceException("Não foi especificado filtro para a busca"); 
     } 

     this.criterion.configure(info); 

     try { 
      Set<Long> retorno = new HashSet<Long>(qtd); 
      byte[] b = new byte[Serializator.BUFFER_SIZE]; 
      int bl = datIn.read(b, 0, Serializator.BUFFER_SIZE); 
      int br = bl, bp = 0, nbp = 0, blockSize, i, p = 0; 

      while (p++ < qtd) { 
       System.out.println("P = "+p); 
       bp = nbp; 
       int aux = ByteArrayUtils.toUnsignedShort(b, bp); 
       System.out.println("aux = "+aux); 
       blockSize = aux + indexBlockSize; 
       System.out.println("indexBlockSize = "+indexBlockSize); 
       System.out.println("blockSize = "+blockSize); 
       if (br < blockSize + 2) { 
        for (i = 0; i < br; i++) { 
         b[i] = b[i + bp]; 
        } 
        bl = datIn.read(b, br, Serializator.BUFFER_SIZE - br) + br; 
        bp = 0; 
        br = bl; 
       } 

       nbp = bp + blockSize; 
       br -= blockSize; 

       System.out.println("b.length = "+b.length); 
       System.out.println("bp = "+bp); 
       System.out.println("headerSize = "+headerSize); 
       if (this.criterion.doCompare(b, bp, headerSize)) { 
        retorno.add(getSearchedValue(b, bp)); 
        if (retorno.size() == this.maxResults) { 
         break; 
        } 
       } 
      } 

      return retorno; 
     } catch (IOException e) { 
      throw new PersistenceException(e); 
     } 
} 

下面的方法中出現的 「執行()」 的代碼:

getSearchValue:)

public long getSearchedValue(byte[] b, int bp) { 
    if (this.fieldReturn == -1) { 
     return ByteArrayUtils.toLong(b, bp + 2); 
    } else { 
     if (b[this.bitSetPosition + bp] >= 0) { 
      int off = ByteArrayUtils.toShort(b, bp + rIndex) + headerSize + bp; 
      return ByteArrayUtils.readOptimizedLong(b, off); 
     } else { 
      return 0; 
     } 
    } 
} 

ByteArraysUtils.toShort(:

public static short toShort(byte[] byteArray, int off) { 
     System.out.println("ByteArrayUtils: toShort: byteArray.length="+byteArray.length 
       +" off = "+off); 
     return (short) ((byteArray[off + 1] & 0xFF) | ((byteArray[off] & 0xFF) << 8)); 
} 

ByteArraysUtils .toUnsignedShort():

public static int toUnsignedShort(byte[] byteArray, int off) { 
     System.out.println("ByteArrayUtils: toUnsignedShort: byteArray.length="+byteArray.length 
       +" off = "+off); 
     return ((int) 0) | ((byteArray[off + 1] & 0xFF) | ((byteArray[off] & 0xFF) << 8)); 
} 

Criterion.doCompare():

public boolean doCompare(byte[] data, int offset, int headerSize) throws PersistenceException { 
    System.out.println("doCompare: data.length = "+data.length+" offset = "+offset 
      +" this.position = "+this.position); 
    if (data[offset + this.position] >= 0) { 
     short off = ByteArrayUtils.toShort(data, offset + this.position); 
     return this.def.verify(data, off + offset + headerSize); 
    } else { 
     return this.def.verifyNull(); 
    } 
} 

下面是執行過程中生成的錯誤的一些日誌:

  • 錯誤1:在COM java.lang.ArrayIndexOutOfBoundsException : 致.wealthsystems.util.api.array.ByteArrayUtils.toShort(ByteArrayUtils.java:123) at com.wealthsystems.persistence.impl.search.criterion.Criterion.doCompare(Criterion.java:64) at com.wealthsystems.persistence.impl.search.DatSearch.execute(DatSearch.java:133)

  • 錯誤2: 6841 LoginActivity Falha日登錄java.lang.ArrayIndexOutOfBoundsException java.lang.ArrayIndexOutOfBoundsException 在com.wealthsystems .persistence.impl.search.criterion.Criterion.doCompare(Criterion.java:61)

  • 錯誤3: 1002575 LoginActivity Falha日登錄java.lang.ArrayIndexOutOfBoundsException java.lang.ArrayIndexOutOfBoundsException 在com.wealthsystems。 util.api.array.ByteArrayUtils.toUnsignedShort(ByteArrayUtils.java:129)

正如我們所看到的,錯誤發生在許多不同的位置,但變量的值總是相同的,即錯誤似乎是隨機的。這是通過打印變量來驗證的(因爲當我們打開調試時錯誤不會發生),通過打印,我們看到變量的奇怪變化。下面是生成的打印的一些例子:

打印1:

P = 746 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 22400 
aux = 100 
indexBlockSize = 58 
blockSize = 158 
b.length = 32767 
bp = 22400 
headerSize = 65 
doCompare: data.length = 32767 offset = 22400 this.position = 10 
ByteArrayUtils: toShort: byteArray.length=32767 off = 22410 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 22465 

P = 747 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 22558 
aux = 99 
indexBlockSize = 58 
blockSize = 157 
b.length = 32767 
bp = 22558 
headerSize = 65 
doCompare: data.length = 32767 offset = 22558 this.position = 10 
java.lang.ArrayIndexOutOfBoundsException 
    at com.wealthsystems.persistence.impl.search.criterion.Criterion.doCompare(Criterion.java:62) 
    at com.wealthsystems.persistence.impl.search.DatSearch.execute(DatSearch.java:121) 
    at com.wealthsystems.persistence.impl.retrieve.DatRetrieve.search(DatRetrieve.java:62) 

注意,在「doCompare()」將被訪問的索引「[偏移+ this.position]」,但該錯誤在索引訪問22568中被指控。該索引小於向量的大小(「data.length」)。

打印2:

P = 578 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 28651 
aux = 114 
indexBlockSize = 58 
blockSize = 172 
b.length = 32767 
bp = 28651 
headerSize = 65 
doCompare: data.length = 32767 offset = 28651 this.position = 10 
ByteArrayUtils: toShort: byteArray.length=32767 off = 28661 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 28716 

P = 579 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 28823 
aux = 114 
indexBlockSize = 58 
blockSize = 22618 
b.length = 32767 
bp = 0 
headerSize = 65 
doCompare: data.length = 32767 offset = 0 this.position = 10 
ByteArrayUtils: toShort: byteArray.length=32767 off = 10 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 65 

P = 580 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 22618 
aux = 65280 
indexBlockSize = 58 
blockSize = 87784 
b.length = 32767 
bp = 0 
headerSize = 65 
doCompare: data.length = 32767 offset = 0 this.position = 10 
P = 581 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 87784 
28493 LoginActivity Falha de login java.lang.ArrayIndexOutOfBoundsException 
java.lang.ArrayIndexOutOfBoundsException 
at com.wealthsystems.util.api.array.ByteArrayUtils.toUnsignedShort(ByteArrayUtils.java:131) 
at com.wealthsystems.persistence.impl.search.DatSearch.execute(DatSearch.java:98) 
at com.wealthsystems.persistence.impl.retrieve.DatRetrieve.search(DatRetrieve.java:62) 

注執行P = 579. 的輔助值是114 indexBlockSize的值是58。BLOCKSIZE值應172.但看來BLOCKSIZE的值= 22618.

打印3:

P = 1 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 0 
aux = 144 
indexBlockSize = 58 
blockSize = 202 
b.length = 32767 
bp = 0 
headerSize = 65 
doCompare: data.length = 32767 offset = 0 this.position = 10 
ByteArrayUtils: toShort: byteArray.length=32767 off = 10 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 65 

P = 2 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 202 
aux = 96 
indexBlockSize = 58 
blockSize = 154 
b.length = 32767 
bp = 202 
headerSize = 65 
doCompare: data.length = 32767 offset = 202 this.position = 10 
ByteArrayUtils: toShort: byteArray.length=32767 off = 212 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 267 

P = 3 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 356 
aux = 115 
indexBlockSize = -7696 
blockSize = -7581 
b.length = 32767 
bp = 356 
headerSize = 65 
doCompare: data.length = 32767 offset = 356 this.position = 10 
ByteArrayUtils: toShort: byteArray.length=32767 off = 366 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = 421 

P = 4 
ByteArrayUtils: toUnsignedShort: byteArray.length=32767 off = -7225 61680 
LoginActivity Falha de login java.lang.ArrayIndexOutOfBoundsException java.lang.ArrayIndexOutOfBoundsException 
at com.wealthsystems.util.api.array.ByteArrayUtils.toUnsignedShort(ByteArrayUtils.java:131) 
at com.wealthsystems.persistence.impl.search.DatSearch.execute(DatSearch.java:98) 
at com.wealthsystems.persistence.impl.retrieve.DatRetrieve.search(DatRetrieve.java:62) 

這是最關鍵的錯誤,因爲變量「indexBlockSize」是私有的,並在構造函數初始化uctor並且不再被修改,但是在運行過程中,它會更改indexBlockSize = -7696(執行P = 3)的值。

設備中發生錯誤:
- IBAK-775(固件:2.1 update1-1.0.0)(內核:2.6.25)(頻率:誤差非常常見); LG Optimus One P500(Android版本:2.2.2)(內核:2.6.32.9)(頻率:錯誤不常見);三星Galaxy Tab GT-P1000(Android:2.2)(頻率:常見錯誤);
- 三星I5800 Galaxy 3(Android 2.2)(頻率:常見錯誤)。

設備中的錯誤從來沒有發生過:
- 以上所有的設備,在Eclipse中的調試模式下運行;
- 任何Android版本的仿真器;摩托羅拉Spice XT300(固件:2.1-update1)(內核:2.6.29); - 三星Galaxy 5(GT-I5500B)(固件:2.1-update1)(內核:2.6.29);
- Motorola Xoom(Android 3.0);
- Samsung Galaxy Tab 8.9(Android 3.0)。

不幸的是,我們無法將外部代碼中的錯誤隔離到我們的應用程序,您能夠重現錯誤。所有試圖將代碼從我們的應用程序中分離出來的嘗試都沒有產生錯誤。但希望你能給我們提供一些關於我們正在發生的事情的信息!

我們在互聯網上對這個錯誤的研究只顯示了這個頁面:http://www.androiddiscuss.com/1-android-discuss/96129.html。看起來像有人遇到類似的問題,但在討論中沒有解決方案。


屬性的聲明和類的構造函數:

private byte fieldReturn; 
private EntityInfo info; 
private final short rIndex, indexBlockSize; 
private ICriterion criterion = null; 
private int headerSize; 
private int maxResults; 
private int bitSetPosition; 

public DatSearch(byte fieldReturn, EntityInfo info) { 
    this.fieldReturn = fieldReturn; 
    this.bitSetPosition = (this.fieldReturn == -1) ? -1 : 10 + (fieldReturn * 2); 
    this.info = info; 
    this.rIndex = (fieldReturn >= 0) ? (short) (10 + (fieldReturn << 1)) : 0; 
    short qtdIndices = (short) info.getMapper().getIndexes().length; 
    this.indexBlockSize = (short) (10 + (qtdIndices << 1)); 
    this.headerSize = indexBlockSize + info.getBitSetLength(); 
} 

我試圖把這一類的所有變量外的其他類,並獲取並設置讀出來,但是這個解決辦法沒有奏效。

+0

1.有多少線程在做這個? 2.你究竟如何定義indexBlockSize變量?而final關鍵字只意味着你不能在其範圍內更改該變量的值,並且該變量超出範圍並且是可修改的。我還有一個想法,請顯示indexBlockSize變量的所有用法以及它的定義。謝謝。 – 2012-01-30 20:45:20

+0

你也可以閱讀關於java和垃圾收集中的可變和不可變對象/類型 – 2012-01-30 21:12:26

+0

1.只有一個線程。 2.我添加了屬性聲明和類構造函數。 indexBlockSize變量僅在此方法中使用且從不寫入。 – user1178849 2012-01-31 11:43:46

回答

0

此問題僅出現在舊設備和舊版Android中。高於2.3版本不會發生。

0

我假設你多次調用你的執行代碼。在這種情況下,不同的線程可能正在訪問您的陣列。當一個正在改變數值時,另一個線程可能正在讀取它們...

看一看java synchronized關鍵字。該關鍵字用於防止不同的線程訪問相同的值。 more about synchronization

所以,讀/寫,並從你的陣列時,請用同步例如這些電話:

byte[] b; 
synchronized(b) 
{ 
    byte[] b = new byte[Serializator.BUFFER_SIZE]; 
} 

synchronized(b) 
{ 
    b[i] = b[i + bp]; 
} 

你可以爲完整的功能也這麼做:

public synchronized long getSearchedValue(byte[] b, int bp) { 
    ... your code 
} 

確保要做到這一點,無論你在哪裏更換正在崩潰的陣列。

+0

它始終是調用該方法的同一個線程。 我們同步了對b和execute()方法的所有訪問。但它沒有奏效。 – user1178849 2012-01-31 12:12:07

+1

在這種情況下,我沒有線索。抱歉! – Entreco 2012-01-31 18:22:31