Примечание. Следующие слова, такие как «мост», «преобразование» и «связывание», в основном та же концепция.
log4j-over-slf4j и slf4j-log4j12-это два пакета JAR, связанные с системой журнала Java. Когда они появляются под участком класса одновременно, они могут вызвать исключения из переполнения стека. Информация об исключении примерно следующим образом (выдержка из официального документа SLF4J, обнаруженного как log4j-over-slf4j.jar, так и SLF4J-log4j12.jar на пути класса, предпочитая StackOverforwerRor):
Исключение в потоке "Main" java.lang.stackoverflowerror
на java.util.hashtable.containskey (hashtable.java:306)
at org.apache.log4j.log4jloggerfactory.getlogger (log4jloggerfactory.java:36)
at org.apache.log4j.logmanager.getlogger (logmanager.java:39)
at org.slf4j.impl.log4jloggerfactory.getlogger (log4jloggerfactory.java:73)
at org.slf4j.loggerfactory.getlogger (loggerfactory.java:249)
at org.apache.log4j.category. <init> (Category.java:53)
at org.apache.log4j.logger .. <init> (logger.java:35)
at org.apache.log4j.log4jloggerfactory.getlogger (log4jloggerfactory.java:39)
at org.apache.log4j.logmanager.getlogger (logmanager.java:39)
at org.slf4j.impl.log4jloggerfactory.getlogger (log4jloggerfactory.java:73)
at org.slf4j.loggerfactory.getlogger (loggerfactory.java:249)
at org.apache.log4j.category .. <init> (Category.java:53)
at org.apache.log4j.logger .. <init> (logger.java:35)
at org.apache.log4j.log4jloggerfactory.getlogger (log4jloggerfactory.java:39)
at org.apache.log4j.logmanager.getlogger (logmanager.java:39)
Последующие строки опущены ...
Существующая система ведения журнала
Прежде чем анализировать конкретные причины этого исключения, необходимо быстро понять существующую систему ведения журнала Java. Следующий рисунок представляет собой диаграмму существующей системы ведения журнала Java:
Приведенная выше картинка не очень точная, но она может четко отображать основную структуру существующей системы журнала Java. Система ведения журнала Java может быть примерно разделена на три части: интерфейс логического фасада, мост и специальная реализация Framework.
Есть много типов фреймворков журнала Java. Самый простой - это собственный java java.util.logging, а самый классический - log4j. Позже появился резерв с лучшей производительностью, чем Log4J, поэтому другие фреймворки журнала не очень часто используются. Приложения, безусловно, могут непосредственно использовать API этих специфических фреймворков журнала для удовлетворения требований к выводу журнала, но поскольку API между каждой системой журнала обычно несовместимы, это заставляет приложение потерять гибкость замены фреймворка для журнала.
Более разумный вариант, чем непосредственно с использованием конкретного API Framework Framework - это использование интерфейса Facade Log. Интерфейс Facade Log обеспечивает набор API, которые не зависят от конкретных фреймворков журнала. Приложения могут отделяться от конкретных фреймворков журнала, используя эти независимые API, что аналогично JDBC. Самым ранним интерфейсом логарированного факультета был общежитие, но самым популярным в настоящее время является SLF4J.
Сам интерфейс фасада журнала обычно не имеет фактической возможности вывода журнала. Ему все еще нужно вызвать конкретный API Framework Framework внизу, то есть его фактически необходимо использовать в сочетании с конкретной структурой журнала. Поскольку существует много конкретных фреймворков и в основном несовместимы друг с другом, если интерфейс логического фасада объединяется с любой системой логарифмической структуры, для этого может потребоваться соответствующий мост, так же, как комбинация между JDBC и различными базами данных требует соответствующего драйвера JDBC.
Следует отметить, что, как упоминалось ранее, вышеупомянутая картина не является точной, это всего лишь основная часть, и фактическая ситуация не всегда является простой односторонней линией «Интерфейс логического факультета-> Bridge-> log Framework». На самом деле, независимые мосты иногда не нужны, и это не просто мост, который преобразует API фасада логарифма в конкретный API Framework Framework. Существуют также мосты, которые преобразуют API Framework Framework в API Facade Log.
Говоря о том, что так называемый «мост»-это не что иное, как псевдо реализация определенного набора API. Эта реализация напрямую не завершает функции, объявленные API, но вызывает другие API с аналогичными функциями. Это завершает переход от «набора API» к «другим API». Если есть два моста: a-to-b.jar и b-to-a.jar, то вы можете представить, что произойдет, когда приложение начнет вызывать API A или B. Это основной принцип исключения переполнения стека, который был впервые введен.
SLF4J переадресация
Выше приведено всего общее объяснение существующей системы ведения журнала Java, и невозможно подробно объяснить проблему. Нам необходимо дополнительно понять ситуацию мостовой между SLF4J и конкретную структуру журнала.
SLF4J мосты до определенной кадры бревна
Следующая картина поступает из официального веб -сайта SLF4J, связывающего документы с рамкой регистрации во время развертывания:
Вы можете видеть, что есть много решений для SLF4J, чтобы сочетаться с конкретными фреймворками. Конечно, самый верхний слой (зеленый слой применения) каждого решения объединяется. Они напрямую называют API, предоставленный SLF4J (легкий абстрактный API-слой) и полагаются на SLF4J-API.JAR. Затем, если вы сделаете API SLF4J вниз, он будет очень свободен, и вы можете использовать почти все конкретные фреймворки. Обратите внимание, что второй слой на рисунке светло -голубой. Глядя на легенду в левом нижнем углу, мы видим, что это представляет собой абстрактный API log, что означает, что они не являются конкретными реализациями. Если нижний слой не объединяется с какой -либо конкретной реализацией фреймворта журнала, такой как первое решение слева, то журнал не может быть выведен ( не уверен, может ли он быть выведен в стандартный выход по умолчанию ).
Третий слой на картинке, очевидно, не такой аккуратный, как первый и второй слои, потому что здесь началась конкретная структура журнала.
Во -первых, давайте посмотрим на два голубых блока озера в середине третьего этажа, которые являются слоем адаптера, то есть мостом. Мост SLF4J-log4J12.jar слева может сказать, что это мост от SLF4J до log4J на основе имени. Точно так же SLF4J-JDK14.JAR справа-мост, реализованный SLF4J для местных журналов Java. Следующий слой из них - соответствующая реализация Framework. Код реализации log4j - log4j.jar, а код реализации JUL уже включен в во время выполнения JVM и не требует отдельного пакета JAR.
Давайте посмотрим на оставшиеся три темно -синих блока на третьем этаже. Эти три из них также являются конкретными реализациями фреймюрных систем, но они не требуют мостов, потому что они сами напрямую реализуют API SLF4J. Само собой разумеется, SLF4J-SIMPLE.JAR и SLF4J-NOP.JAR, вы можете сказать, что один-это простая реализация SLF4J, а другой-пустая реализация SLF4J, которая не очень полезна в обычное время. Причина, по которой «Регистратор» также реализует API SLF4J, заключается в том, что Hourback и SLF4J принадлежат тому же человеку, который также является автором Log4J.
Все пакеты с серыми банками в третьем слое имеют красные коробки, что означает, что все они напрямую реализуют API SLF4J. Тем не менее, реализация API SLF4J с помощью Blue Blue Bridge не выводит напрямую, но вместо этого вызывает API других логарифмических фреймворков.
Другие фреймворки API вызовы обратно в SLF4J
Если существуют только вышеперечисленные мосты от SFL4J до других фреймворков журнала, не может быть никаких проблем. Но на самом деле, есть другой тип моста, чьи функции точно противоположны вышеперечисленному, они преобразуют API других логарифмических каркасов в API SLF4J. Следующая картина поступает из официального веб -сайта SLF4J Document Document Bridge APIS:
На приведенном выше рисунке показаны все три случая, которые до сих пор могут безопасно перезвонить в SLF4J из других API -интерфейсов.
В качестве примера в качестве первого случая в верхнем левом углу, когда базовый SLF4J соединяется с фреймворком для резервы, API -интерфейсы Log Framework, которые позволяют верхнему слою обратно обратно в SLF4J, включают Log4J и Jul. Хотя JCL не является конкретной реализацией платформы регистрации, его API все еще может быть вызван обратно в SLF4J. Чтобы реализовать преобразование, метод состоит в том, чтобы заменить исходную банку с кадром бревен на определенную банку моста, указанную на рисунке. Следует отметить, что API авторитета в API SLF4J не включает преобразование API резерва, потому что авторитет изначально является реализацией API SLF4J.
После прочтения трех ситуаций вы обнаружите, что почти все API других бревенчатых рамок, включая JCL API, могут быть перенаправлены обратно в SLF4J по желанию. Но существует единственное ограничение того, что фреймворк, который вызывает обратно в SLF4J, не может быть таким же, как в рамках журнала, к которой в настоящее время соединяется SLF4J. Это ограничение состоит в том, чтобы не допустить, чтобы A-B.Jar и B-to-A.Jar одновременно появляются в классе, что приводит к тому, что A и B постоянно будут постоянно звонить друг другу, и, наконец, переполнены. В настоящее время это ограничение не гарантируется технологиями, а только самим разработчиком. Вот почему официальный сайт SLF4J подчеркивает, что все разумные методы находятся только в трех ситуациях на картинке выше.
На этом этапе принцип исключения, показанного в начале, был в основном ясен. Кроме того, из приведенного выше рисунка мы видим, что могут быть комбинации, аналогичные исключениям, не только log4j-over-slf4j и slf4j-log4j12. Официальный сайт SLF4J также указал на другую пару: JCL-Over-Slf4j.jar и SLF4J-jcl.jar.
Пример кода
Предыдущий анализ теоретический. Даже если log4j-over-slf4j и slf4j-log4j12 используются одновременно в фактическом коде, исключения не обязательно могут произойти. Следующий код вызывает API SLF4J для вывода журнала, а SLF4J соединяется с Log4J:
Пакет Test; открытый класс Helloworld {public static void main (string [] args) {org.apache.log4j.basicconfigurator.configure (); org.slf4j.logger logger = org.slf4j.loggerfactory.getlogger (helloworld.class);Настройте ClassPath для настройки пакета JAR (обратите внимание, что log4j до log4j-over-slf4j):
В этом случае запуск тестовой программы может нормально выводить журнал, и не будет исключения переполнения стека. Но если вы отрегулируете заказ JAR на пути к классу:
Запуск тестовой программы снова приведет к тому, что исключение переполнения стека, аналогичное первоначальному переполнению стека в этой статье. Вы можете увидеть очевидные периодические повторения:
Анализ графика последовательности
Приведенная выше изображение представляет собой подробную диаграмму столбца программы вызовов переполнения стека. Начиная с вызова 1, вызов 1.1, 1.1.1 ... Наконец, когда он достигает 1.1.1.1.1 (последний вызов на рисунке) обнаруживается, что он точно такой же, что и 1, поэтому последующий процесс полностью повторяется.
Следует отметить, что начальный предохранитель не только loggerfactory.getLogger (), показанный на рисунке. В приложении есть несколько других прямых вызовов, которые могут запустить исключения из переполнения стека. Например, в предыдущем примере код первого оператора org.apache.log4j.basicconfigurator.configure () на самом деле является первым утверждением org.apache.log4j.basicconfigurator.configure (), но последующий взаимный процесс бесконечного уточнения в основном представляет собой предыдущую фигуру.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.