我最近在应用程序中看到奇怪的行为,我无法解释。 他们发生非常罕见,所以我不能再现他们。 虽然这些问题发生的地方发生了变化,但通用部分似乎是在数组创build后(我知道,这是不可能的,因此:奇怪的行为)数组改变大小。
有几个例子可以明确我的观点:
java.lang.StringIndexOutOfBoundsException: String index out of range: 86 at java.lang.String.checkBounds(String.java:409) at java.lang.String.<init>(String.java:577) at com.acunia.fleet.diagnostics.providers.tacho.VDOKLineInputParser.getRealDriverID(Unknown Source)
这将导致这样的代码:
public String getRealDriverID(byte[] buffer) { if (buffer.length > 86 && isDriverCardInserted(buffer)) { return new String(buffer, 70, 16); } return null; }
所以我们首先检查缓冲区是否足够大(超过86字节),然后再尝试从它们中创build一个string。
第二个例子:
java.lang.ArrayIndexOutOfBoundsException: -1 at java.lang.String.lastIndexOf(String.java:1889) at java.lang.String.lastIndexOf(String.java:1835) at java.lang.String.lastIndexOf(String.java:1817) at com.acunia.service.position.nmea.comm.CommPositionProvider.isValid(Unknown Source)
导致此exception的行是:
int csi = line.lastIndexOf("*");
我看了一下openjdk的String.java源码,但是找不到错误,除非数组在创build后突然开始改变大小。
网上唯一可以find的参考资料是openjdk的bug: https ://bugs.openjdk.java.net/browse/JDK-6817012。 虽然这个bug被标记为“不是问题”,但是在阅读本文时,我不能确定所提到的问题是否被认为是bug,或者如果closures该bug的人不明白为什么这个bug会造成问题。
如果有人遇到类似的问题,我真的很感激听到。 就目前而言,问题太不稳定,无法通过使用其他版本的openjdk来解决问题。
问题出现在:
hardware: custom arm platform java version "1.6.0_31" OpenJDK Runtime Environment (IcedTea6 1.13.3) (6b31-1.13.3-1~deb7u1) OpenJDK Zero VM (build 23.25-b01, mixed mode) Linux 3.2.0 #1 Fri Jun 20 10:25:16 CEST 2014 armv7l GNU/Linux
这很可能是字节和系统字符集的问题。 该文档明确指出:
当给定字节在默认字符集中无效时,此构造函数的行为是未指定的 。
你可以通过明确地提供正确的字符集来避开这个问题:
new String(buffer, 70, 16, StandardCharsets.UTF_8)
您正在使用byte[]
数组创建新的String
而不指定Charset
。 因此,我的猜测是,系统默认字符集已经改变,你看到的行为改变。 我建议总是明确指定字符集。 例如:
return new String(buffer, 70, 16, "UTF-8");