Java 字符串#等于抛出ArrayIndexOutOfBoundException
stacktrace相当长,但这里是相关部分Java 字符串#等于抛出ArrayIndexOutOfBoundException,java,Java,stacktrace相当长,但这里是相关部分 Caused by: java.lang.ArrayIndexOutOfBoundsException: 33 at java.lang.String.equals(String.java:1018) at java.util.HashMap.get(HashMap.java:305) 因此,当我从HashMap中检索元素时,将调用String#equals。然后,如果(v1[i++]!=v2[j++]) 这真的很糟糕 更新。异常是从日志
Caused by: java.lang.ArrayIndexOutOfBoundsException: 33
at java.lang.String.equals(String.java:1018)
at java.util.HashMap.get(HashMap.java:305)
因此,当我从HashMap
中检索元素时,将调用String#equals。然后,如果(v1[i++]!=v2[j++])
这真的很糟糕
更新。异常是从日志分析程序获取的。我没有在那里使用反射。我还认为字符串对象被破坏了,但没有从代码中得到任何线索。重新启动后,此问题不会重现。如果我继续重试,我不知道它是否会重现
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);
}
}
公共静态映射解析行(字符串行){
if(StringUtils.isEmpty(行)){
return Collections.emptyMap();
}
String[]parts=StringUtils.split(第“\t”行);
映射结果=新的HashMap();
用于(字符串部分:部分){
String[]keyVal=StringUtils.split(部分“=”,2);
如果(keyVal.length==2){
字符串key=keyVal[0];
字符串值=keyVal[1];
结果。输入(键、值);
}
}
返回结果;
}
公共静态无效进程(字符串文件名、日期、闭包)引发IOException{
InputStream=null;
读取器r=null;
试一试{
is=新文件输入流(getFilename(文件名,日期));
is=新的BufferedInputStream(is);
is=新的GZIPInputStream(is);
r=新的InputStreamReader(即“utf8”);
LineIterator iter=IOUtils.LineIterator(r);
while(iter.hasNext()){
String line=iter.nextLine();
Map Map=LogUtils.parseLine(line);
closure.execute(map);
}
}最后{
IOUtils.close(r);
IOUtils.安静地关闭(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... */
}
public void execute(映射行){
if(dataMap==null){
dataMap=newhashmap();
}
String identifier=line.get(Constants.identifier_KEY);//从此处引发异常
/*……布拉布拉*/
}
为了简单起见,我将创建一个closure对象并用它调用
LogUtils.process
。LogUtils将行(例如:key1=value1\tkey2=value2\t…kn=valuen
)拆分为一个HashMap
。然后LogUtils
将映射传递给闭包。异常是从line.get(Constants.IDENTIFIER\u KEY)抛出的代码>当Constants.IDENTIFIER_键是静态最终字段时。因此equals方法的lhs和rhs是一个静态的最终字符串,返回值为StringUtils.split(第“\t”行)
。我检查了commons-lang的代码。它实际上是一个字符串#子字符串。所以它仍然是正确的。这基本上表明有什么东西正在破坏字符串对象。很容易复制:
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));
}
}
。。。但我们不知道在您的情况下,字符串是否真的是这样损坏的。这表明i或j超出了该数组的限制。@veer:我不这么认为。想象一下如果n
以0开头。。。有了你的版本,它永远不会终止。@yegong你能给我们看更多的代码吗?e、 g.插入和访问映射的内容
@JonSkeet等代码方法不是我的实现。它是Java1.6的源代码。@rhyon没问题。但它是java.lang.String#equals。此处不应出现ArrayIndexOutOfBoundException。我粘贴的代码没有反射。我同意损坏的字符串对象。但是,代码似乎非常简单,没有任何东西试图打开字符串并修改最终字段。
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));
}
}