java - Apache HttpClient 中未修改的 ArrayList 中的 ConcurrentModificationException

标签 java concurrency java-7

如果在生产中抛出 ConcurrentModificationException,抛出的列表是普通的 java7 ArrayList,该列表不会在循环中修改并且是上述方法的本地 - 不会传递到其他任何地方。

每次调用 api 时都会持续抛出异常,直到服务器重新启动 - 然后它停止。

java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.next(ArrayList.java:837)
    at org.apache.http.impl.cookie.BestMatchSpec.formatCookies(BestMatchSpec.java:175)
    at org.apache.http.client.protocol.RequestAddCookies.process(RequestAddCookies.java:174)
    at org.apache.http.protocol.ImmutableHttpProcessor.process(ImmutableHttpProcessor.java:131)

代码在下面但很难在 IDE 之外阅读,这里是 GrepCode在进行调用的地方,看到 matchedCookies 没有传递到线程范围之外。

BestMatchSpec.formatCookies 不修改 cookies 列表:

public List<Header> formatCookies(final List<Cookie> cookies) {
    Args.notNull(cookies, "List of cookies");
    int version = Integer.MAX_VALUE;
    boolean isSetCookie2 = true;
    for (final Cookie cookie: cookies) {
        if (!(cookie instanceof SetCookie2)) {
            isSetCookie2 = false;
        }
        if (cookie.getVersion() < version) {
            version = cookie.getVersion();
        }
    }

调用方法 RequestAddCookies.process 构造列表并且不会使 cookie 列表对另一个线程可用。

public void process(final HttpRequest request, final HttpContext context)
        throws HttpException, IOException {
...
    // Find cookies matching the given origin
    final List<Cookie> matchedCookies = new ArrayList<Cookie>();
    final Date now = new Date();
    for (final Cookie cookie : cookies) {
        if (!cookie.isExpired(now)) {
            if (cookieSpec.match(cookie, cookieOrigin)) {
                if (this.log.isDebugEnabled()) {
                    this.log.debug("Cookie " + cookie + " match " + cookieOrigin);
                }
                matchedCookies.add(cookie);
            }
        } else {
            if (this.log.isDebugEnabled()) {
                this.log.debug("Cookie " + cookie + " expired");
            }
        }
    }
    // Generate Cookie request headers
    if (!matchedCookies.isEmpty()) {
        final List<Header> headers = cookieSpec.formatCookies(matchedCookies);
...
}

我错过了什么吗?

最佳答案

感谢@guido 在 apache 上指出这个问题。这是由于 java7u60 中修复的 JIT 编译器的错误。代码不应产生 ConcurrentModificationException。

HttpClient 报告: https://issues.apache.org/jira/browse/HTTPCLIENT-1173

Java 错误: http://bugs.java.com/view_bug.do?bug_id=8021898

测试重现错误: https://github.com/rholder/jvm-loop-unswitching-bug

关于java - Apache HttpClient 中未修改的 ArrayList 中的 ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23830234/

相关文章:

java - 将 jBLAS 与 NVBLAS 结合使用

java - 如何在不拆分字符串的情况下检查字符串是否具有某种模式?

java - Java中线程的终止条件

c++ - 是否可以在不锁定或提供 future 的情况下进行查找或创建?

java - 未找到 java.nio 的最新添加内容;使用java 1.7.0_9

java - 如何用整数替换字符串中的字符?

Java:无限while循环中的If语句

java - 线程有自己的数据副本吗?

android - 需要在 Android 上使用 RXJava 的简单 map()、reduce() 示例,无需 Java 8 lambda

java - 针对多个用户输入的多个异常处理