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.3.3へのソフトリンクである4.1があることを意味しますか?クラスローダーがロードしているものを出力すると、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を実行したときのみです。
提案をありがとう、
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にこのクラスのどのバージョンが含まれているかが明確にわかります。
1つのバージョン(4.3.3)しかない場合、これは、他のバージョンがアプリを実行しているコンテナーからのものであることを意味する必要があります。これを解決する方法は、コンテナによって異なります。
複数のバージョンが見つかった場合は、プロジェクトでhttpcore
への一時的な依存関係をグローバルに除外してみてください(第51.4.7節 ユーザーガイド )。
特定の構成の除外を定義すると、この構成または継承構成を解決するときに、除外された推移的な依存関係がすべての依存関係に対してフィルター処理されます。
-verbose:classを指定してjvmを開始すると、どのクラスがどこからロードされているかが表示されます。
私は過去に次の2つのシナリオでそのような問題を抱えていました。
ロードしているjarの1つに、不正なバージョンのhttpcoreを参照するClasspath句を含むマニフェストがあります。
独自のクラスローダーを備えたいくつかのコンテナー(Tomcatまたはsth)内で実行していて、いくつかのクラスがロードされている。別の瓶からの容器によって。
また、GenieClientのクラスローダーを明示的に使用しているため、クラスのリソースを示すコードは機能しないと思います。おそらくBasicLineFormatter.class.getClassloader()
を使用すると、異なる結果が得られます。しかし、-verbose:class
。
明らかに、クラスパスに古いバージョンのBasicLineFormatter
があり、DEFAULT
ではなくINSTANCE
フィールドがあります。 e.g を参照してください。
しかし、クラスローダーがhttpcore-4.3.3を使用していることを報告しており、Gradle依存関係ツリーがそれをバックアップしています。
そのため、古いバージョンのBasicLineFormatter
が含まれている他のJARがあるようです。依存関係JARを調べて、そこにあるかどうかを確認する必要がある場合があります。 jar tf *.jar | grep 'BasicLineFormatter'
は、関係する可能性のあるJARを確認します。
また、これが関連する可能性があります。私はあなたのタグを見て、あなたはいくつかのAndroid=開発を行っているようです。したがって、次のスタックオーバーフロー question は興味深いかもしれません:
それが正確な問題ではない場合でも、適切なhttpcore依存関係がある場合でも、古いBasicLineFormatter
がどのようにぶら下がっている可能性があるかがわかります。