Подтвердить что ты не робот

NoSuchFieldError INSTANCE на 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, что является мягкой ссылкой на 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,

Большое спасибо за любые предложения,

4b9b3361

Ответ 1

org.apache.httpcomponents:httpcore:4.1 -> 4.3.3 означает, что 4.1 - запрошенная версия, которая разрешена 4.3.3 по разрешению конфликта. Выполнение чего-то вроде gradle -q dependencyInsight --configuration compile --dependency httpcore должно дать вам больше информации об этом.

Вы должны проверить вывод сборки и посмотреть, какие банки фактически упакованы вместе с вашим приложением. Кроме того, используя некоторый файловый менеджер, выполните поиск BasicLineFormatter.class через вывод сборки (включая архивы, конечно), это должно дать вам определенный ответ, какие банки содержат какую версию этого класса.

Если есть только одна версия (4.3.3), это означает, что другая версия происходит из контейнера, в котором выполняется ваше приложение. Способы разрешения этого зависят от контейнера.

Если вы найдете несколько версий, вы можете попробовать исключить транзитивную зависимость до httpcore по всему миру в проекте (глава 51.4.7 руководства ).

Если вы определяете исключение для конкретной конфигурации, исключенная транзитивная зависимость будет фильтроваться для всех зависимостей при разрешении этой конфигурации или любой наследующей конфигурации.

Ответ 2

Начните свой jvm с -verbose: class, он покажет, какой класс загружается из.

У меня были такие проблемы в прошлом в двух сценариях:

  • Одна из загружаемых банок имеет манифест с предложением Classpath, который ссылается на неверную версию httpcore.

  • вы работаете в каком-то контейнере (tomcat или sth) с собственными загрузчиками классов и загружаете некоторые классы, например. контейнером из другой банки.

Я также не думаю, что ваш код, показывающий ресурс для класса, работает так, как он явно использует GenieClient classloader. Вероятно, использование BasicLineFormatter.class.getClassloader() даст разные результаты. Но лучше попробуйте -verbose:class.

Ответ 3

Кажется, что BasicLineFormatter получил свою статическую ссылку INSTANCE in 4.3-beta1 и ссылка

Ответ 4

Очевидно, что существует некоторая более старая версия BasicLineFormatter в вашем пути к классам, в которой есть поле DEFAULT вместо INSTANCE. См. например.

Но ваш загрузчик классов сообщает, что вы используете httpcore-4.3.3, а ваше дерево зависимостей Gradle поддерживает это.

Итак, похоже, что у вас есть другой JAR, в котором есть старая версия BasicLineFormatter. Возможно, вам придется пройти через JAR с зависимостями и просто посмотреть, находится ли он там. Попробуйте jar tf *.jar | grep 'BasicLineFormatter', чтобы увидеть, какие JAR могут быть задействованы.

Кроме того, это может быть актуальным. Я посмотрел на ваши теги, и, похоже, у вас есть разработка Android. Таким образом, может возникнуть интерес к следующему переполнению стека question:

Даже если это не точная проблема, она показывает, как можно повесить старый BasicLineFormatter, даже если у вас есть правильная зависимость httpcore.

Ответ 5

  • найдите httpcore, который имеет более старую версию, чем 4.3
  • удалить устаревшую версию httpcore jar из ссылочных библиотек.