org.apache.http.impl.io.DefaultHttpRequestWriterFactory中的NoSuchFieldError INSTANCE

时间:2015-01-13 11:27:08

标签: java gradle apache-httpclient-4.x

java version "1.7.0_71" 
Gradle 2.1

您好,

UPDATE:

依赖项

gradle dependencies | grep httpcore
|    +--- org.apache.httpcomponents:httpcore:4.3.3
|    +--- org.apache.httpcomponents:httpcore:4.3.3
|    +--- org.apache.httpcomponents:httpcore:4.3.3
|    +--- org.apache.httpcomponents:httpcore:4.3.3
|    |         |    |         |    +--- org.apache.httpcomponents:httpcore:4.1 -> 4.3.3
|    +--- org.apache.httpcomponents:httpcore:4.3.3
|    |         |    |         |    +--- org.apache.httpcomponents:httpcore:4.1 -> 4.3.3

这是否意味着我有4.1这是4.3.3的软链接?看起来很奇怪,因为当我打印出类加载器正在加载它时,似乎加载了4.3.3:/home/steve/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.3.3/f91b7a4aadc5cf486df6e4634748d7dd7a73f06d/httpcore-4.3.3.jar似乎很奇怪。

当我尝试运行我的httpClient时,我一直收到此错误。一切都编好了。

java.lang.NoSuchFieldError: INSTANCE
        at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:52

我的代码非常简单,删除了不重要的代码以保持小:

public class GenieClient {
    private CloseableHttpClient mClient;

    public GenieClient() {
        ClassLoader classLoader = GenieClient.class.getClassLoader();
        URL resource = classLoader.getResource("org/apache/http/message/BasicLineFormatter.class");
        log.log(Level.INFO, "resource: " + resource);

        mClient = HttpClientBuilder.create().build();
    }

    public int sendRequest() {   
        int responseCode = -1;

        try {
            HttpResponse response = mClient.execute(new HttpPost("http://www.google.com"));
            responseCode = response.getStatusLine().getStatusCode();
        }
        catch(IOException ex) {
            log.log(Level.SEVERE, "IOException: " + ex.getMessage());
        }

        return responseCode;
    }
}

我从classLoader获得的输出是:

INFO: resource: jar:file:/home/steve/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.3.3/f91b7a4aadc5cf486df6e4634748d7dd7a73f06d/httpcore-4.3.3.jar!/org/apache/http/message/BasicLineFormatter.class

我使用gradle作为我的构建工具,并在我的build.gradle文件中设置了这样的依赖项:

dependencies {
    compile 'org.apache.httpcomponents:httpclient:4.3.6'
}

我还尝试包含以下httpcore,但仍然会出现同样的错误:

compile 'org.apache.httpcomponents:httpcore:4.4'

一切都建立好,只有当我运行我的httpClient时才会这样做,

非常感谢任何建议,

5 个答案:

答案 0 :(得分:5)

使用-verbose:class启动你的jvm,它将显示从哪里加载哪个类。

我过去在两种情况下遇到过这样的问题:

  1. 您正在加载的其中一个jar有一个带有Classpath子句的清单,该子句引用了不正确的httpcore版本。

  2. 你在一个带有自己的类加载器的容器(tomcat或sth)中运行,并且加载了一些类,例如来自不同罐子的容器。

  3. 我也不认为显示该类资源的代码可以正常使用GenieClient的类加载器。可能使用BasicLineFormatter.class.getClassloader()会产生不同的结果。 但最好尝试使用-verbose:class

答案 1 :(得分:5)

org.apache.httpcomponents:httpcore:4.1 -> 4.3.3表示4.1是请求的版本,通过冲突解决方案解析为4.3.3。执行gradle -q dependencyInsight --configuration compile --dependency httpcore之类的内容可以让您更深入地了解这一点。

您应该检查构建输出,并查看实际与您的应用程序一起打包的jar。此外,使用一些文件管理器通过构建输出(当然包括档案)运行搜索BasicLineFormatter.class,这应该给你一个明确的答案,哪些罐子包含这个类的哪个版本。

如果只有一个版本(4.3.3),则必须表示其他版本来自运行应用程序的容器。解决这个问题的方法取决于容器。

如果找到多个版本,可以尝试在项目中全局排除传递依赖关系httpcoreuser guide的第51.4.7节)。

  

如果为特定配置定义排除,则在解析此配置或任何继承配置时,将针对所有依赖项筛选排除的传递依赖关系。

答案 2 :(得分:4)

似乎BasicLineFormatter的静态INSTANCE in 4.3-beta1 linklink

答案 3 :(得分:2)

显然,您的类路径中存在一些BasicLineFormatter的旧版本,其中一个版本具有DEFAULT字段而不是INSTANCE。请参阅e.g

但是您的类加载器报告您正在使用httpcore-4.3.3,并且您的Gradle依赖关系树支持它。

所以看起来你有一些其他JAR的旧版本BasicLineFormatter。您可能需要查看依赖项JAR,然后查看它是否在那里。尝试jar tf *.jar | grep 'BasicLineFormatter'查看可能涉及的JAR。

此外,此可能相关。我看了你的标签,似乎你做了一些Android开发。因此,以下Stack Overflow question可能会引起关注:

即使这不是确切的问题,它也会显示即使您拥有正确的httpcore依赖关系,您也可能会有一个旧的BasicLineFormatter

答案 4 :(得分:2)

  1. 查找版本低于4.3的httpcore
  2. 从Referenced Libraries中删除旧版本的httpcore jar。