참고 : "브리지", "변환"및 "바인딩"과 같은 다음 단어는 기본적으로 동일한 개념입니다.
Log4J-Over-SLF4J 및 SLF4J-LOG4J12는 Java 로그 시스템과 관련된 2 개의 JAR 패키지입니다. 클래스 경로 아래에 동시에 나타나면 스택 오버플로 예외가 발생할 수 있습니다. 예외 정보는 대략 다음과 같습니다 (SLF4J 공식 웹 사이트 문서에서 발췌 한 클래스 경로에서 log4j-over-slf4j.jar 및 slf4j-log4j12.jar를 모두 감지했습니다.
스레드의 예외 "main"java.lang.stackoverflowerror
at 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 로깅 시스템은 대략 세 가지 부분으로 나눌 수 있습니다 : 로그 페이드 인터페이스, 브리지 및 로그 프레임 워크 특정 구현.
Java 로깅 프레임 워크에는 여러 유형이 있습니다. 가장 간단한 것은 Java 자신의 java.util.logging이고 가장 고전적인 것은 Log4J입니다. 나중에 Log4J보다 성능이 향상 된 로그백이 나타나므로 다른 로그 프레임 워크가 일반적으로 사용되지 않습니다. 응용 프로그램이 이러한 특정 로그 프레임 워크의 API를 직접 사용하여 로그 출력 요구 사항을 충족 할 수 있지만, 각 로그 프레임 워크 사이의 API는 일반적으로 호환되지 않기 때문에 응용 프로그램이 로그 프레임 워크를 교체 할 수있는 유연성을 잃게됩니다.
특정 로그 프레임 워크 API를 직접 사용하는 것보다 더 합리적인 옵션은 로그 페이드 인터페이스를 사용하는 것입니다. 로그 페이드 인터페이스는 특정 로그 프레임 워크와 무관 한 API 세트를 제공합니다. 응용 프로그램은 JDBC와 유사한 이러한 독립적 인 API를 사용하여 특정 로그 프레임 워크에서 분리 할 수 있습니다. 가장 초기의 로그 페이스 페이스 인터페이스는 커먼즈 로깅 이었지만 현재 가장 인기있는 것은 SLF4J입니다.
로그 파사이드 인터페이스 자체에는 일반적으로 실제 로그 출력 기능이 없습니다. 여전히 하단에서 특정 로그 프레임 워크 API를 호출해야합니다. 즉, 실제로 특정 로그 프레임 워크와 함께 사용해야합니다. 특정 로그 프레임 워크가 많고 서로 호환되지 않기 때문에 로그 페이드 인터페이스가 모든 로그 프레임 워크와 결합되면 JDBC와 다양한 데이터베이스 간의 조합에 해당 JDBC 드라이버가 필요한 것처럼 해당 브리지가 필요할 수 있습니다.
앞에서 언급했듯이 위의 그림은 정확하지 않으며, 이것은 주된 부분 일 뿐이며 실제 상황은 항상 "로그 페이드 인터페이스-> 브리지-> 로그 프레임 워크"의 단순한 일방화 라인이 아닙니다. 실제로, 독립적 인 교량은 때때로 필요하지 않으며, 로그 페이스 페이드 API를 특정 로그 프레임 워크 API로 변환하는 브리지가 아닙니다. 로그 프레임 워크 API를 로그 페이드 API로 변환하는 교량도 있습니다.
무뚝뚝하게 말하면, 소위 "브리지"는 특정 API 세트의 의사 구현에 지나지 않습니다. 이 구현은 API가 선언 한 함수를 직접 완료하지는 않지만 다른 API를 유사한 기능으로 호출합니다. 이로 인해 "API 세트"에서 "기타 API"로의 전환이 완료됩니다. A-to-B.jar 및 B-to-A.jar라는 두 개의 다리가있는 경우 응용 프로그램이 A 또는 B의 API를 호출하기 시작할 때 어떤 일이 발생할지 상상할 수 있습니다. 이것은 처음 도입 된 스택 오버플로 예외의 기본 원리입니다.
SLF4J 전달 결합
위의 것은 기존 Java 로깅 시스템에 대한 일반적인 설명 일 뿐이며 문제를 자세히 설명 할 수 없습니다. SLF4J와 특정 로그 프레임 워크 간의 브리징 상황을 더 이해해야합니다.
SLF4J는 특정 로그 프레임에 브리지입니다
다음 그림은 배포 시간에 로깅 프레임 워크와 함께 SLF4J 공식 웹 사이트 문서 바인딩에서 나옵니다.
SLF4J가 특정 로그 프레임 워크와 결합 할 수있는 많은 솔루션이 있음을 알 수 있습니다. 물론 각 솔루션의 최상층 (녹색 응용 층)이 통합됩니다. 그들은 SLF4J (Light Blue Abstract API 레이어)가 제공 한 API를 직접 호출하고 SLF4J-API.jar에 의존합니다. 그런 다음 SLF4J API를 아래쪽으로 수행하면 매우 무료이며 거의 모든 특정 로깅 프레임 워크를 사용할 수 있습니다. 그림의 두 번째 레이어는 밝은 파란색입니다. 왼쪽 하단 모서리의 범례를 살펴보면 이것이 추상 로그 API를 나타내는 것을 알 수 있습니다. 즉, 구체적인 구현이 아님을 의미합니다. 하단 계층이 왼쪽의 첫 번째 솔루션과 같은 특정 로그 프레임 워크 구현과 결합되지 않으면 로그를 출력 할 수 없습니다 ( 기본적으로 표준 출력으로 출력 될 수 있는지 확실하지 않음 ).
특정 로그 프레임 워크가 여기에 관련되기 시작했기 때문에 그림의 세 번째 층은 첫 번째 및 두 번째 레이어만큼 깔끔하지 않습니다.
먼저, 3 층 중간에있는 두 개의 호수 블루 블록, 즉 어댑터 레이어, 즉 교량을 살펴 보겠습니다. 왼쪽의 SLF4J-LOG4J12.JAR 브리지는 이름에 따라 SLF4J에서 LOG4J까지의 다리임을 알 수 있습니다. 마찬가지로, 오른쪽의 SLF4J-JDK14.jar는 SLF4J에서 Java 기본 로그에서 구현 한 브리지입니다. 다음 계층은 해당 로그 프레임 워크 구현입니다. Log4J의 구현 코드는 log4j.jar이며 JUL 구현 코드는 이미 JVM 런타임에 포함되어 있으며 별도의 JAR 패키지가 필요하지 않습니다.
3 층에 나머지 3 개의 진한 파란색 블록을 살펴 보겠습니다. 그 중 세 가지는 또한 특정 로깅 프레임 워크 구현이지만 SLF4J API를 직접 구현하기 때문에 다리가 필요하지 않습니다. 말할 것도없이, SLF4J-Simple.jar 및 SLF4J-NOP.jar는 하나는 SLF4J의 간단한 구현이고 다른 하나는 SLF4J의 빈 구현이라는 것을 알 수 있습니다. Logback이 SLF4J API를 구현하는 이유는 Logback과 SLF4J가 Log4J의 저자이기도 한 사람의 출신이기 때문이라고합니다.
세 번째 레이어의 모든 회색 항아리 패키지에는 빨간색 상자가있어 SLF4J API를 직접 구현합니다. 그러나 Lake Blue Bridge에 의한 SLF4J API의 구현은 로그를 직접 출력하지 않고 대신 다른 로그 프레임 워크의 API를 호출합니다.
다른 로그 프레임 워크 API는 SLF4J로 돌아갑니다
SFL4J에서 다른 로그 프레임 워크까지의 위의 교량 만 존재한다면 아무런 문제가 없을 수 있습니다. 그러나 실제로 다른 유형의 브리지가 있는데, 그 기능은 위의 것과 정확히 반대이며 다른 로그 프레임 워크의 API를 SLF4J API로 변환합니다. 다음 그림은 SLF4J 공식 웹 사이트 문서 브리지 레거시 API에서 제공됩니다.
위의 그림은 지금까지 다른 로그 프레임 워크 API에서 SLF4J로 안전하게 호출 할 수있는 세 가지 사례를 모두 보여줍니다.
기본 SLF4J가 로그백 프레임 워크로 연결되면 왼쪽 상단 코너에서 첫 번째 케이스를 예로 들어 보면 상단 계층이 SLF4J로 다시 연결할 수있는 로그 프레임 워크 API에는 LOG4J 및 JUL을 포함합니다. JCL은 로깅 프레임 워크의 구체적인 구현은 아니지만 API는 여전히 SLF4J로 다시 호출 할 수 있습니다. 변환을 구현하려면 원래 로그 프레임 병을 그림에 나열된 특정 브리지 항아리로 바꾸는 방법이 있습니다. 로그백은 원래 SLF4J API의 구현이기 때문에 SLF4J API에 대한 로그백 API에는 로그백 API의 변환이 포함되지 않는다는 점에 유의해야합니다.
세 가지 상황을 읽은 후에는 JCL API를 포함한 다른 로그 프레임 워크의 거의 모든 API가 SLF4J로 다시 리디렉션 될 수 있음을 알 수 있습니다. 그러나 SLF4J로 다시 호출하는 로그 프레임 워크가 SLF4J가 현재 브리징하는 로그 프레임 워크와 동일 할 수 없다는 유일한 제한 사항이 있습니다. 이 제한은 A-to-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가 실제 코드에서 동시에 사용 되더라도 예외가 반드시 발생하지는 않습니다. 다음 코드는 SLF4J의 API를 호출하여 로그를 출력하고 SLF4J는 LOG4J로 연결됩니다.
패키지 테스트; public class helloworld {public static void main (string [] args) {org.apache.log4j.basicconfigurator.configure (); org.slf4j.logger logger = org.slf4j.loggerfactory.getlogger (helloworld.class);jar 패키지 구성을 위해 클래스 경로를 구성합니다 (log4j는 log4j-over-slf4j 이전) :
이 경우 테스트 프로그램을 실행하면 로그를 정상적으로 출력 할 수 있으며 스택 오버플로 예외가 없습니다. 그러나 ClassPath에서 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을 더 지원하기를 바랍니다.