2012-01-30 88 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