Use the same classpath ordering for an exploded jar and an archive
Print classloader urls in main method:
public static void main(String[] args) { URLClassLoader classLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader(); for(URL url : classLoader.getURLs()) { System.err.println(url); } SpringApplication.run(DemoApplication.class, args); }
- Run as jar
mvn clean package -DskipTests $ java -jar target/demo-0.0.1-SNAPSHOT.jar
output:
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/spring-boot-starter-1.5.3.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/spring-boot-1.5.3.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/spring-context-4.3.8.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/spring-aop-4.3.8.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/spring-beans-4.3.8.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/spring-expression-4.3.8.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/spring-boot-autoconfigure-1.5.3.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/spring-boot-starter-logging-1.5.3.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/logback-classic-1.1.11.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/logback-core-1.1.11.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/jcl-over-slf4j-1.7.25.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/jul-to-slf4j-1.7.25.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/log4j-over-slf4j-1.7.25.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/spring-core-4.3.8.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/snakeyaml-1.17.jar!/
jar:file:/private/tmp/demo/target/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/slf4j-api-1.7.25.jar!/
- Run in directory
cd target unzip demo-0.0.1-SNAPSHOT.jar -d demo cd demo java org.springframework.boot.loader.PropertiesLauncher
output:
file:/private/tmp/demo/target/demo/BOOT-INF/classes/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/jcl-over-slf4j-1.7.25.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/jul-to-slf4j-1.7.25.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/log4j-over-slf4j-1.7.25.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/logback-classic-1.1.11.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/logback-core-1.1.11.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/slf4j-api-1.7.25.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/snakeyaml-1.17.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/spring-aop-4.3.8.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/spring-beans-4.3.8.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/spring-boot-1.5.3.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/spring-boot-autoconfigure-1.5.3.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/spring-boot-starter-1.5.3.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/spring-boot-starter-logging-1.5.3.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/spring-context-4.3.8.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/spring-core-4.3.8.RELEASE.jar!/
jar:file:/private/tmp/demo/target/demo/BOOT-INF/lib/spring-expression-4.3.8.RELEASE.jar!/
The order of classLoader urls is very important.
When run app in exploded directory, the order of jars is different.
I recommend add a index file BOOT-INF/INDEX.LIST to save the order of jars.
See also: