0

スタック トレースはかなり長いですが、関連するセクションを次に示します。

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 が呼び出されます。次に、行からスローされた ArrayIndexOutOfBoundExceptionif (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;
}

本当に変です。


アップデート。例外は、ログ分析プログラムから取得されます。そこではリフレクションを使用しませんでした。また、文字列オブジェクトが破損している何かについても考えましたが、コードからは何の手がかりも得られませんでした。そして、この問題は再起動後に再現しませんでした。リトライし続けると再現するかどうかわかりません。

  1. 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);
        }
    }
    
  2. 閉鎖

    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、マップをクロージャーに渡します。line.get(Constants.IDENTIFIER_KEY);また、 Constants.IDENTIFIER_KEY が static final フィールドの場合から例外がスローされます。したがって、equals メソッドの lhs および rhs は静的な最終文字列であり、戻り値はStringUtils.split(line, '\t')です。commons-lang のコードを確認しました。実物String#substringです。それで、それはまだ奇妙です。

4

1 に答える 1

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));
    }
}

...しかし、それが実際にあなたの状況で文字列が破損した方法であるかどうかはわかりません.

于 2012-09-03T06:03:46.033 に答える