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

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.(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文件中设置了这样的依赖build.gradle

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

我也尝试包含以下httpcore,但仍然得到相同的错误:

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

一切都建立好,只有当我运行我的httpClient时,

非常感谢任何建议,

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

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

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

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

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

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

我过去在两个场景中遇到过这样的问题:

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

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

我也不认为您的代码显示该类的资源,因为它显式使用GenieClient的类加载器。 可能使用BasicLineFormatter.class.getClassloader()会给出不同的结果。 但最好尝试使用-verbose:class

似乎BasicLineFormatter INSTANCE in 4.3-beta1 链接和链接中获得了静态INSTANCE in 4.3-beta1

显然,类路径上有一些旧版本的BasicLineFormatter ,它具有DEFAULT字段而不是INSTANCE 。 见例如 。

但是你的类加载器报告你正在使用httpcore-4.3.3,而你的Gradle依赖树支持它。

因此,似乎您有一些其他JAR,其中包含旧版本的BasicLineFormatter 。 您可能需要查看依赖项JAR,然后查看它是否在那里。 尝试一下jar tf *.jar | grep 'BasicLineFormatter' jar tf *.jar | grep 'BasicLineFormatter'可以查看可能涉及哪些JAR。

此外,这可能是相关的。 我看了你的标签,看来你做了一些Android开发。 因此,以下Stack Overflow 问题可能会引起关注:

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

  1. 找到比4.3更旧版本的httpcore
  2. 从Referenced Libraries中删除旧版本的httpcore jar。