org.apache.http.impl.io.DefaultHttpRequestWriterFactory 处的 NoSuchFieldError 实例
NoSuchFieldError INSTANCE at org.apache.http.impl.io.DefaultHttpRequestWriterFactory
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 是 link 到 4.3.3 的软版本?看起来很奇怪,因为当我打印出 class 加载器正在加载的内容时,它似乎加载了 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,
非常感谢您的任何建议,
用 -verbose:class 启动你的 jvm,它会显示哪个 class 从哪里加载。
我过去在两种情况下遇到过这样的问题:
您正在加载的其中一个 jar 有一个带有 Classpath 子句的清单,它引用了错误版本的 httpcore。
您 运行 在某个容器(tomcat 或某物)中,带有自己的 class 加载器,并且加载了一些 classes,例如通过来自不同罐子的容器。
我也不认为您显示 class 资源的代码有效,因为它明确使用了 GenieClient 的 classloader。可能使用 BasicLineFormatter.class.getClassloader()
会给出不同的结果。
但最好尝试 -verbose:class
.
很明显,您的类路径中有一些旧版本的 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
闲逛。
org.apache.httpcomponents:httpcore:4.1 -> 4.3.3
表示4.1
是请求的版本,通过冲突解决被解析为4.3.3
。执行类似 gradle -q dependencyInsight --configuration compile --dependency httpcore
的操作应该会让您对此有更多了解。
您应该检查构建输出,看看您的应用实际打包了哪些 jar。此外,使用一些文件管理器 运行 通过构建输出(当然包括存档)搜索 BasicLineFormatter.class
,这应该会给你一个明确的答案什么 jars 包含这个 class 的什么版本.
如果只有一个版本 (4.3.3),这一定意味着另一个版本来自 运行安装您的应用程序的容器。解决这个问题的方法取决于容器。
如果你确实找到了多个版本,你可以尝试在项目中全局排除对httpcore
的传递依赖(user guide的第51.4.7章)。
If you define an exclude for a particular configuration, the excluded transitive dependency will be filtered for all dependencies when resolving this configuration or any inheriting configuration.
似乎 BasicLineFormatter
得到了它的静态 INSTANCE in 4.3-beta1
link and link
- 查找版本低于 4.3 的 httpcore
- 从引用的库中删除旧版本的 httpcore jar。
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 是 link 到 4.3.3 的软版本?看起来很奇怪,因为当我打印出 class 加载器正在加载的内容时,它似乎加载了 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,
非常感谢您的任何建议,
用 -verbose:class 启动你的 jvm,它会显示哪个 class 从哪里加载。
我过去在两种情况下遇到过这样的问题:
您正在加载的其中一个 jar 有一个带有 Classpath 子句的清单,它引用了错误版本的 httpcore。
您 运行 在某个容器(tomcat 或某物)中,带有自己的 class 加载器,并且加载了一些 classes,例如通过来自不同罐子的容器。
我也不认为您显示 class 资源的代码有效,因为它明确使用了 GenieClient 的 classloader。可能使用 BasicLineFormatter.class.getClassloader()
会给出不同的结果。
但最好尝试 -verbose:class
.
很明显,您的类路径中有一些旧版本的 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
闲逛。
org.apache.httpcomponents:httpcore:4.1 -> 4.3.3
表示4.1
是请求的版本,通过冲突解决被解析为4.3.3
。执行类似 gradle -q dependencyInsight --configuration compile --dependency httpcore
的操作应该会让您对此有更多了解。
您应该检查构建输出,看看您的应用实际打包了哪些 jar。此外,使用一些文件管理器 运行 通过构建输出(当然包括存档)搜索 BasicLineFormatter.class
,这应该会给你一个明确的答案什么 jars 包含这个 class 的什么版本.
如果只有一个版本 (4.3.3),这一定意味着另一个版本来自 运行安装您的应用程序的容器。解决这个问题的方法取决于容器。
如果你确实找到了多个版本,你可以尝试在项目中全局排除对httpcore
的传递依赖(user guide的第51.4.7章)。
If you define an exclude for a particular configuration, the excluded transitive dependency will be filtered for all dependencies when resolving this configuration or any inheriting configuration.
似乎 BasicLineFormatter
得到了它的静态 INSTANCE in 4.3-beta1
link and link
- 查找版本低于 4.3 的 httpcore
- 从引用的库中删除旧版本的 httpcore jar。