堆栈跟踪很长,但这是相关部分。
Caused by: java.lang.ArrayIndexOutOfBoundsException: 33
at java.lang.String.equals(String.java:1018)
at java.util.HashMap.get(HashMap.java:305)
所以,当我从 HashMap<String,?>
检索一个元素时, String#equaqls 被调用。然后,从行 if (v1[i++] != v2[j++])
抛出 ArrayIndexOutOfBoundException
// Sun java 1.6
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
确实很奇怪。
<小时/>更新。异常(exception)是从日志分析程序中获取的。我在那里没有使用反射。我还考虑过某些东西损坏了字符串对象,但没有从代码中得到任何线索。并且重启后没有再出现这个问题。我不知道如果我不断重试它是否会重现。
LogUtils
public static Map<String, String> parseLine(String line) { if (StringUtils.isEmpty(line)) { return Collections.emptyMap(); } String[] parts = StringUtils.split(line, '\t'); Map<String, String> results = new HashMap<String, String>(); for (String part : parts) { String[] keyVal = StringUtils.split(part, "=", 2); if (keyVal.length == 2) { String key = keyVal[0]; String value = keyVal[1]; results.put(key, value); } } return results; } public static void process(String fileName, Date date, Closure closure) throws IOException { InputStream is = null; Reader r = null; try { is = new FileInputStream(getFilename(fileName, date)); is = new BufferedInputStream(is); is = new GZIPInputStream(is); r = new InputStreamReader(is, "utf8"); LineIterator iter = IOUtils.lineIterator(r); while (iter.hasNext()) { String line = iter.nextLine(); Map<String, String> map = LogUtils.parseLine(line); closure.execute(map); } } finally { IOUtils.closeQuietly(r); IOUtils.closeQuietly(is); } }
关闭
public void execute(Map<String, String> line) { if (dataMap == null) { dataMap = new HashMap<String, Map<Long, Integer>>(); } String identifier = line.get(Constants.IDENTIFIER_KEY); // Exception thrown from there /* ...blahblah... */ }
为了简单起见,我将创建一个闭包对象并调用 LogUtils.process
用它。 LogUtils 将行(例如: key1=value1\tkey2=value2\t...kn=valuen
)换成 HashMap
。然后LogUtils
将把 map 传递给闭包。并且异常是从 line.get(Constants.IDENTIFIER_KEY);
抛出的。当 Constants.IDENTIFIER_KEY 是静态最终字段时。所以equals方法的lhs和rhs是一个静态的final String,返回值是StringUtils.split(line, '\t')
。我检查了commons-lang的代码。这是String#substring
实际上。所以它仍然很奇怪。
最佳答案
这基本上表明某些东西正在破坏字符串对象。复制起来很容易:
import java.lang.reflect.*;
public class Test {
public static void main(String[] args) throws Exception {
String x = "hello";
String y = new String("xhell");
Field field = String.class.getDeclaredField("offset");
field.setAccessible(true);
field.set(y, 1);
System.out.println(x.equals(y));
}
}
...但我们不知道这是否实际上是在您的情况下字符串被损坏的方式。
关于java - String#equals 抛出 ArrayIndexOutOfBoundException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12242688/