Как подавить SLF4J Предупреждение о нескольких привязках?

Мой проект java имеет зависимости от разных версий SLF4J. Как подавить раздражающие предупреждения?

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:xyz234/lib/slf4j-
log4j12-1.5.8.jar!/org/slf4j/impl/StaticLoggerBinder.class]

SLF4J: Found binding in [jar:file:xyz123/.m2/repository/org/slf4j/slf4j-log4j12
/1.6.0/slf4j-log4j12-1.6.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.

PS: Это не тот же вопрос, что и slf4j, предупреждающий о дублировании одного и того же дубликата, ответ заключается в том, как избавиться от ложного предупреждения о тревоге, в однако мой случай - это настоящее предупреждение. P.S.S.: Извините, я забыл упомянуть: я использую Maven и SLF4J включен в зависимости от моих зависимостей.

Ответы

Ответ 1

Удалите один из slf4j-log4j12-1.5.8.jar или slf4j-log4j12-1.6.0.jar из пути к классам. Ваш проект не должен зависеть от разных версий SLF4J. Я предлагаю вам использовать только 1.6.0.

Если вы используете Maven, вы можете исключить транзитивные зависимости. Вот пример:

<dependency>
    <groupId>com.sun.xml.stream</groupId>
    <artifactId>sjsxp</artifactId>
    <version>1.0.1</version>
    <exclusions>
        <exclusion>
            <groupId>javax.xml.stream</groupId>
            <artifactId>stax-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

С текущей реализацией slf4j-api невозможно удалить эти предупреждения. Класс org.slf4j.LoggerFactory печатает сообщения:

  ...
  if (implementationSet.size() > 1) {
    Util.report("Class path contains multiple SLF4J bindings.");
    Iterator iterator = implementationSet.iterator();
    while(iterator.hasNext()) {
      URL path = (URL) iterator.next();
      Util.report("Found binding in [" + path + "]");
    }
    Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");
  }
  ...

Класс Util следующий:

public class Util {

  static final public void report(String msg, Throwable t) {
    System.err.println(msg);
    System.err.println("Reported exception:");
    t.printStackTrace();
  }
  ...

Метод report записывается непосредственно в System.err. Обходным решением может быть замена System.err System.setErr() перед первым вызовом LoggerFactory.getLogger(), но вы можете потерять другие важные сообщения, если вы это сделаете что.

Конечно, вы можете загрузить исходный код и удалить эти вызовы Util.report и использовать измененный slf4j-api в своем проекте.

Ответ 2

Прочитали ли вы URL-адрес, на который ссылается предупреждение?

SLF4J: See [http://www.slf4j.org/codes.html#multiple_bindings][1] for an explanation.

Вот что говорится в ссылке:

SLF4J API предназначен для связывания с одним и только одним основным протоколированием за один раз. Если в классе присутствует более одного привязки путь, SLF4J выдает предупреждение, в котором перечислены местоположения этих привязок. Когда это произойдет, выберите одну и только одну привязку к вам хотите использовать и удалить другие привязки.

Например, если у вас есть как slf4j-simple-1.6.2.jar, так и slf4j-nop-1.6.2.jar на пути к классу, и вы хотите использовать nop (без операции), затем удалите slf4j-simple-1.6.2.jar из путь класса.

Обратите внимание, что предупреждение, выданное SLF4J, - это только предупреждение. SLF4J будет по-прежнему связываться с первой структурой, которую он находит на пути к классу.

Ответ 3

    PrintStream filterOut = new PrintStream(System.err) {
        public void println(String l) {
            if (! l.startsWith("SLF4J")) {
                super.println(l);
            }
        }
    };
    System.setErr(filterOut);

и вуаля!

Ответ 4

Если вы используете старую версию Jetty (скажем, Jetty 6), вам может потребоваться изменить порядок загрузки классов для webapp, чтобы сделать его более приоритетным, чем контейнер. Вы можете сделать это, добавив эту строку в файл xml контейнера:

<Set name="parentLoaderPriority">false</Set>

Ответ 5

Если использование maven всегда использует команду

mvn dependency:tree

В этом списке будут указаны все зависимости, добавленные к проекту, включая зависимости от включенных банок. Здесь мы можем указать несколько версий или несколько копий банок, которые входят в другие банки, которые были добавлены. Используйте

<exclusions><exclusion><groupId></groupId><artifactId></artifactId></exclusion></exclusions>

в элементе <dependency>, чтобы исключить конфликты. Всегда повторяйте команду maven выше после каждого исключения, если проблема сохраняется.

Ответ 6

Иногда исключение 2-го регистратора из пути к классу потребовало бы слишком много искажений, и предупреждение невероятно раздражает. Маскировка стандартной ошибки в самом начале программы, кажется, работает, например

    public static void main(String[] args)
    {
        org.apache.log4j.Logger.getRootLogger().setLevel(org.apache.log4j.Level.OFF);
        PrintStream old = System.err;
        System.setErr(new PrintStream(new ByteArrayOutputStream()));
        // ... trigger it ...
        System.setErr(old);

        ...

в результате чего trigger it должен вызывать некоторую функцию nop, которая обращается к системе ведения журнала и в противном случае вызвала бы генерацию сообщения.

Я не рекомендовал бы это для производственного кода, но для целей skunkworks это должно помочь.