Spring Boot: ClassLoader 의 계승 관계 와 영향 깊이
10325 단어 classloaderspringboot자바
spring boot 자체 의 작 동 원리 에 대한 분석 은 다음 과 같 습 니 다.http://hengyunabc.github.io/s...
Spring boot 의 ClassLoader 계승 관계
아래 에 제 공 된 demo 를 실행 할 수 있 습 니 다. 각각 다른 장면 에서 실행 할 수 있 습 니 다. 서로 다른 장면 에서 Spring boot 응용 프로그램의 ClassLoader 계승 관 계 를 알 수 있 습 니 다.
https://github.com/hengyunabc...
세 가지 상황 으로 나 뉜 다.
IDE 에서 직접 run main 함수
Spring 의 ClassLoader 는 바로 System ClassLoader 입 니 다.ClassLoader 의 urls 는 모든 jar 와 자신의 것 을 포함 합 니 다
target/classes
========= Spring Boot Application ClassLoader Urls =============
ClassLoader urls: sun.misc.Launcher$AppClassLoader@2a139a55
file:/Users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/classes/
file:/Users/hengyunabc/.m2/repository/org/springframework/cloud/spring-cloud-starter/1.1.9.RELEASE/spring-cloud-starter-1.1.9.RELEASE.jar
file:/Users/hengyunabc/.m2/repository/org/springframework/boot/spring-boot-starter/1.4.7.RELEASE/spring-boot-starter-1.4.7.RELEASE.jar
...
fat jar 로 실행
mvn clean package
java -jar target/demo-classloader-context-0.0.1-SNAPSHOT.jar
응용 프로그램의 main 함 수 를 실행 하 는 ClassLoader 는
LaunchedURLClassLoader
이 고, parent 는 SystemClassLoader
입 니 다.
========= ClassLoader Tree=============
org.springframework.boot.loader.LaunchedURLClassLoader@1218025c
- sun.misc.Launcher$AppClassLoader@6bc7c054
-- sun.misc.Launcher$ExtClassLoader@85ede7b
또한
LaunchedURLClassLoader
의 urls 는 fat jar 의 BOOT-INF/classes!/
디 렉 터 리 와 BOOT-INF/lib
의 모든 jar 입 니 다.
========= Spring Boot Application ClassLoader Urls =============
ClassLoader urls: org.springframework.boot.loader.LaunchedURLClassLoader@1218025c
jar:file:/Users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/
jar:file:/Users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/spring-boot-1.4.7.RELEASE.jar!/
jar:file:/Users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/spring-web-4.3.9.RELEASE.jar!/
...
SystemClassLoader
의 urls 는 demo-classloader-context-0.0.1-SNAPSHOT.jar
자체 이다.
========= System ClassLoader Urls =============
ClassLoader urls: sun.misc.Launcher$AppClassLoader@6bc7c054
file:/Users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-SNAPSHOT.jar
디 렉 터 리 압축 풀기 로 실행
mvn clean package
cd target
unzip demo-classloader-context-0.0.1-SNAPSHOT.jar -d demo
cd demo
java org.springframework.boot.loader.PropertiesLauncher
응용 프로그램의 main 함 수 를 실행 하 는 ClassLoader 는
LaunchedURLClassLoader
이 고, parent 는 SystemClassLoader
입 니 다.
========= ClassLoader Tree=============
org.springframework.boot.loader.LaunchedURLClassLoader@4aa298b7
- sun.misc.Launcher$AppClassLoader@2a139a55
-- sun.misc.Launcher$ExtClassLoader@1b6d3586
LaunchedURLClassLoader
의 urls 는 디 렉 터 리 에 있 는 BOOT-INF/classes/
과 /BOOT-INF/lib/
아래 의 jar 가방 입 니 다.
========= Spring Boot Application ClassLoader Urls =============
ClassLoader urls: org.springframework.boot.loader.LaunchedURLClassLoader@4aa298b7
file:/Users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/BOOT-INF/classes/
jar:file:/Users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/BOOT-INF/lib/bcpkix-jdk15on-1.55.jar!/
jar:file:/Users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/BOOT-INF/lib/bcprov-jdk15on-1.55.jar!/
jar:file:/Users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/BOOT-INF/lib/classmate-1.3.3.jar!/
SystemClassLoader
의 urls 는 현재 디 렉 터 리 만 있 습 니 다:
========= System ClassLoader Urls =============
ClassLoader urls: sun.misc.Launcher$AppClassLoader@2a139a55
file:/Users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/
사실 두 가지 운행 방식 이 있다.
mvn spring-boot:run
와mvn spring-boot:run -Dfork=true
그러나 비교적 적 게 사용 하고 따로 토론 하지 않 습 니 다.흥미 가 있 으 면 스스로 뛰 어 내 릴 수 있다.spring boot 에서 ClassLoader 의 계승 관 계 를 정리 합 니 다.
LaunchedURLClassLoader
가 있 습 니 다. parent 는 System ClassLoader LaunchedURLClassLoader
의 urls 는 fat jar 의 BOOT-INF/classes
와 BOOT-INF/lib
의 jar 입 니 다.SystemClassLoader 의 urls 는 fat jar 자체 입 니 다.spring boot 1. 3. 1. 4. 버 전의 차이 점
spring boot 1, 3. * 버 전에 서
/lib
아래 에 놓 습 니 다.spring boot 1.4. * 버 전 후
BOOT-INF/classes
디 렉 터 리 에 포장 합 니 다 /lib
아래 에 놓 습 니 다.spring boot 1.4 의 포장 구조 변경 은 이 commt 가 도입 한 것 입 니 다.
https://github.com/spring-pro...
이 commt 의 본 의 는 classloader 의 계승 관 계 를 간소화 하고 직관 적 인 parent 우선 방식 으로
LaunchedURLClassLoader
을 실현 하 는 동시에 포장 구조 와 전통 적 인 war 가방 응용 이 더욱 가깝다 는 것 이다.그러나 이 변경 은 많은 복잡 한 문 제 를 일 으 켰 다. 위 에서 우리 가 분석 한 ClassLoader 계승 관 계 는 좀 어 지 러 웠 다.
현재 의 ClassLoader 계승 관계 가 가 져 온 영향
많은 사용자 들 이 일부 코드 가 IDE 에서 잘 달리 지만 실제 배치 가 실 행 될 때 작 동 하지 않 는 다 는 것 을 발견 할 수 있 습 니 다.ClassLoader 의 구조 로 인해 발생 하 는 경우 가 많 습 니 다. 다음은 사례 를 분석 하 겠 습 니 다.
demo.jar!/BOOT-INF/classes!/
이렇게 url 은 작 동 하지 않 습 니 다.spring boot 는 표준 jar 프로 토 콜 을 확장 하여 다 층 jar in jar, 그리고 directory in jar 를 지원 합 니 다.spring boot 응용 시작 원리 분석 참조
spring boot 1.3 에 서 는 jar in jar 가 있 지만 비교적 건장 한 코드 는 이러한 상황 을 처리 할 수 있 습 니 다. 예 를 들 어 tomcat 8 은 스스로 jar in jar 를 지원 합 니 다.
그러나 대부분의 코드 는
demo.jar!/BOOT-INF/classes!/
와 같은 directory in jar 의 다 중 url 을 지원 하지 않 기 때문에 spring boot 1.4 에 서 는 많은 라 이브 러 리 코드 가 효력 을 잃 습 니 다.demo.jar!/META-INF/resources
하의 자원 문제servlet 3.0 규범 에서 정적 자원 을
META-INF/resources
아래 에 두 면 servlet container 는 읽 기 를 지원 합 니 다.그러나 위의 상속 결과 에서 우 리 는 한 가지 문 제 를 발견 할 수 있다.LaunchedURLClassLoader
LaunchedURLClassLoader
의 urls 는 fat jar 자체 src/main/resources/META-INF/resources
디 렉 터 리 가 fat jar 에 포장 되 었 습 니 다. 즉 demo.jar!/META-INF/resources
LaunchedURLClassLoader
의 parent 이렇게 해서 이상 한 현상 을 일 으 켰 다.
META-INF/resources
자원 을 얻 을 수 있 습 니 다 LaunchedURLClassLoader
이 고 자신의 ClassLoader 만 스 캔 하기 때 문 입 니 다 urls
META-INF/resources
에 두 면 접근 할 수 있 습 니 다. 자원 을 자신의 main 함수 src/main/resources/META-INF/resources
에 두 었 을 때 접근 할 수 없습니다 질문
getResource("")
의 미 는 ClassLoader 의 url 을 되 돌려 주 는 첫 번 째 url 입 니 다. 사용자 들 은 이것 이 자신의 classes 디 렉 터 리 나 jar 의 url 이 라 고 생각 할 때 가 많 습 니 다.그러나 실제로 ClassLoader 가 url 목록 을 불 러 올 때 임 의 성 이 있 기 때문에 OS 저층 실현 과 관련 이 있 기 때문에 url 의 순서 가 모두 같다 고 보장 할 수 없습니다.그래서
getResources("")
돌아 오 는 결과 가 다 를 때 가 많다.그러나 많은 라 이브 러 리 나 이 코드 에 의존 하여 스 캔 자원 을 찾 으 면 spring boot 에서 작 동 하지 않 습 니 다.
또 주의해 야 할 것 은 스프링 부 트 가 세 가지 다른 형식 으로 실행 되 고
getResource("")
되 돌아 오 는 결과 도 다르다 는 점 이다.사용 자 는 데모 의 코드 를 스스로 바 꾸 어 결 과 를 인쇄 할 수 있 습 니 다.한 마디 로 하면 이 두 API 에 의존 하지 말고 자원 을 넣 어 포 지 셔 닝 하 는 것 이 좋다.또는 spring 자체 가 제공 하 는 자원 검색 체 제 를 직접 이용 합 니 다.
질문
사용 자 는 여러 개의 코드 모듈 을 가지 고 있 으 며, 서로 다른 모듈 아래 에 여러 개의
getResource("")
spring 프로필 을 놓 았 습 니 다.사용자 가 유사 한
getResources("")
어댑터 를 사용 하여 자원 을 불 러 오 면 IDE 에서 뛸 때 올 바 르 게 불 러 올 수 있 지만 fat jar 에 서 는 불 러 올 수 없 는 문제 가 발생 할 수 있 습 니 다.spring 자신의 문서 에서 관련 해석 을 볼 수 있 습 니 다.
https://docs.spring.io/spring...
WARNING: Note that "classpath
:" when combined with Ant-style patterns will only work reliably with at least one root directory before the pattern starts, unless the actual target files reside in the file system. This means that a pattern like "classpath:*.xml" will not retrieve files from the root of jar files but rather only from the root of expanded directories. This originates from a limitation in the JDK's ClassLoader.getResources() method which only returns file system locations for a passed-in empty String (indicating potential roots to search). This ResourcePatternResolver implementation is trying to mitigate the jar root lookup limitation through URLClassLoader introspection and "java.class.path" manifest evaluation; however, without portability guarantees.
즉,
classpath*:**-service.xml
을 사용 하여 다른 jar 가방 과 일치 할 때 디 렉 터 리 가 앞 에 있어 야 합 니 다. 그렇지 않 으 면 일치 하지 않 습 니 다. 이것 은 ClassLoader. getResources () 함수 로 인 한 것 입 니 다.IDE 에서 뛸 때 응용 에 의존 하 는 다른 모듈 은 보통 하나의
*-service.xml
디 렉 터 리 이기 때문에 문제 가 없다.그러나 fat jar 로 달 릴 때 다른 모듈 은 하나의 jar 로 포장 되 어
classpath*:**-service.xml
아래 에 놓 여 있 기 때문에 이 때 는 연결 이 실패 합 니 다.총결산
classpath*
포장 형식 은 뚜렷 한 장점 이 있다. 더욱 뚜렷 하고 war 가방 의 형식 에 가깝다.횡 운 단 령 칼럼
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
주석 매핑 및 빈 유효성 검사은 새로운 주석 유형 매핑 기능을 추가합니다. 생성된 인터페이스 및 클래스에 추가 주석을 추가할 수 있는 가능성을 제공합니다. 현재 openapi-processor는 Spring Boot 및 Micronaut에 대한...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.