Reputation: 1197
I have a spring-boot "fat" jar (1.5.22) with embedded tomcat (tomcat-embed-core-8.5.57.jar).
Inside the jar - there are many "inner" jars under BOOT-INF/lib.
In what order are those inner jars loaded by the class-loader?
If I run java -jar myFatSpringBoot.jar
on multiple computers - will inner jars be picked up in the same exact order, or does it "depend" on something on each computer? (FS/tmpfs/java/etc)
UPDATE: many responders indicated it takes inner jars in the exact order in which they appear in the fat jar (so at least the QA and PROD should behave same way for same fat jar, unlike it was for non-spring-boot .war apps).
Now I'm wondering if we have any machinery to preserve/enforce/specify the order of inner jars during the process of creating/packaging the jar? (maven/gradle/...)
Upvotes: 4
Views: 4118
Reputation: 1
I cannot confirm that the index (BOOT-INF/classpath.idx
) is respected in runtime for the fatjar (Spring Boot 3.1.5
).
The same can be said about BOOT-INF/classes
.
The order fully depends on a packager.
The LaunchedURLClassLoader
reads entries from the fat jar using URLs provided by java.util.jar.JarFile.stream()
, following the order provided by the JarFile
. Entries in the stream appear in the same order as they do in the central directory of the jar file.
This means that the files listed first have priority. In other words, the position in the archive defines the priority making the order depend entirely on the packager, but not on the loader.
To check this, simply remove the BOOT-INF/classes
and BOOT-INF/lib
folders from the jar archive first and then try copying classes
and lib
one by one in alternating order.
If classes are copied first, the class from classes
will be loaded by the classloader. Conversely, if lib
is copied first, then the class from lib
will be loaded.
Same with jars - the order depends on the place in the archive - classpath.idx
was not respected.
PS: Checked on org.springframework.boot.loader.LaunchedURLClassLoader
.
Upvotes: 0
Reputation: 116051
The jars in BOOT-INF/lib
are always added to Spring Boot’s class loader in the order in which they appear in the jar. This means that if you have the same class file or resource declared in multiple jars, the same one will always win across multiple runs of your application, irrespective of operating system, Java version, etc. This holds true even if you're using Spring Boot's support for automatically unpacking certain jars at runtime.
Spring Boot also packages a BOOT-INF/classpath.idx
index file in each jar that it builds. It lists all of the nested jars "in the order that they should be added to the classpath". If you unzip the jar file such that the jars in BOOT-INF/lib
are then ordered by the filesystem, if you continue to use Spring Boot's JarLauncher
to launch the application it will honour the order in the index.
Spring Boot contains tests, such as these, that verify the ordering of the classpath, both when launching an application using java -jar
and when using java org.springframework.boot.loader.JarLauncher
.
Upvotes: 7
Reputation: 9102
I think the order will remain same. It's generally the JRE related classes and then the application. You can actually see the loading order yourself. Just launch the program with -verbose
flag. Something like this
java -verbose -jar myFatSpringBoot.jar
This will print lots of information on what class is being loaded from which jar and which path. Apart from startup there will be few classes which will get loaded when your application is being used as generally the class-loading is lazy. You can log this info to an external file and later analyze.
java -verbose -jar myFatSpringBoot.jar > log.txt
Upvotes: 1