堆栈跟踪很长,但这是相关部分。
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++])
// 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;
}
这真的很糟糕。
更新。例外是来自日志分析程序。我没有在那里使用反射。我还想到了一些损坏字符串对象的东西,但没有从代码中获得任何线索。这个问题在重新启动后没有重现。如果我继续重试,我不知道它是否会重现。
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
会将地图传递给闭包。当Constants.IDENTIFIER_KEY是静态最终字段时,异常从line.get(Constants.IDENTIFIER_KEY);
抛出。所以equals方法的lhs和rhs是一个静态的最终String,返回值为StringUtils.split(line, '\t')
。我查了一下commons-lang的代码。实际上是String#substring
。所以它仍然很糟糕。
答案 0 :(得分:2)
这基本上表明某些东西正在破坏字符串对象。它很容易重现:
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));
}
}
...但是我们不知道实际上是字符串在你的情况下是否被破坏的方式。