From 2578e81796fed7da7f07a19c3c965ea0339ffafa Mon Sep 17 00:00:00 2001 From: Filip Hrisafov Date: Fri, 17 Jul 2026 12:44:03 +0200 Subject: [PATCH 1/2] Fix nested archive paths logging in PropertiesLauncher See gh-50968 Signed-off-by: Filip Hrisafov --- .../loader/launch/PropertiesLauncher.java | 5 +--- .../launch/PropertiesLauncherTests.java | 24 +++++++++---------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/loader/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/PropertiesLauncher.java b/loader/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/PropertiesLauncher.java index e31d15243275..eddebc7e102f 100644 --- a/loader/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/PropertiesLauncher.java +++ b/loader/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/PropertiesLauncher.java @@ -136,8 +136,6 @@ public class PropertiesLauncher extends Launcher { private final File homeDirectory; - private final List paths; - private final Properties properties = new Properties(); public PropertiesLauncher() throws Exception { @@ -148,7 +146,6 @@ public PropertiesLauncher() throws Exception { this.archive = archive; this.homeDirectory = getHomeDirectory(); initializeProperties(); - this.paths = getPaths(); this.classPathIndex = getClassPathIndex(this.archive); } @@ -295,7 +292,7 @@ private void addToSystemProperties() { private List getPaths() throws Exception { String path = getProperty(PATH); List paths = (path != null) ? parsePathsProperty(path) : Collections.emptyList(); - debug.log("Nested archive paths: %s", this.paths); + debug.log("Nested archive paths: %s", paths); return paths; } diff --git a/loader/spring-boot-loader/src/test/java/org/springframework/boot/loader/launch/PropertiesLauncherTests.java b/loader/spring-boot-loader/src/test/java/org/springframework/boot/loader/launch/PropertiesLauncherTests.java index d12b13bf8f3a..d434c8ec1b96 100644 --- a/loader/spring-boot-loader/src/test/java/org/springframework/boot/loader/launch/PropertiesLauncherTests.java +++ b/loader/spring-boot-loader/src/test/java/org/springframework/boot/loader/launch/PropertiesLauncherTests.java @@ -127,7 +127,7 @@ void testUserSpecifiedConfigName() throws Exception { System.setProperty("loader.config.name", "foo"); this.launcher = new PropertiesLauncher(); assertThat(this.launcher.getMainClass()).isEqualTo("my.Application"); - assertThat(ReflectionTestUtils.getField(this.launcher, "paths")).hasToString("[etc/]"); + assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[etc/]"); } @Test @@ -141,14 +141,14 @@ void testRootOfClasspathFirst() throws Exception { void testUserSpecifiedDotPath() throws Exception { System.setProperty("loader.path", "."); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(this.launcher, "paths")).hasToString("[.]"); + assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[.]"); } @Test void testUserSpecifiedSlashPath() throws Exception { System.setProperty("loader.path", "jars/"); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(this.launcher, "paths")).hasToString("[jars/]"); + assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[jars/]"); Set urls = this.launcher.getClassPathUrls(); assertThat(urls).areExactly(1, endingWith("app.jar")); } @@ -158,7 +158,7 @@ void testUserSpecifiedWildcardPath() throws Exception { System.setProperty("loader.path", "jars/*"); System.setProperty("loader.main", "demo.Application"); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(this.launcher, "paths")).hasToString("[jars/]"); + assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[jars/]"); this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -168,7 +168,7 @@ void testUserSpecifiedJarPath() throws Exception { System.setProperty("loader.path", "jars/app.jar"); System.setProperty("loader.main", "demo.Application"); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(this.launcher, "paths")).hasToString("[jars/app.jar]"); + assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[jars/app.jar]"); this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -177,7 +177,7 @@ void testUserSpecifiedJarPath() throws Exception { void testUserSpecifiedRootOfJarPath() throws Exception { System.setProperty("loader.path", "jar:file:./src/test/resources/nested-jars/app.jar!/"); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(this.launcher, "paths")) + assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")) .hasToString("[jar:file:./src/test/resources/nested-jars/app.jar!/]"); Set urls = this.launcher.getClassPathUrls(); assertThat(urls).areExactly(1, endingWith("foo.jar!/")); @@ -216,7 +216,7 @@ void testUserSpecifiedNestedJarPath() throws Exception { System.setProperty("loader.path", "nested-jars/nested-jar-app.jar!/BOOT-INF/classes/"); System.setProperty("loader.main", "demo.Application"); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(this.launcher, "paths")) + assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")) .hasToString("[nested-jars/nested-jar-app.jar!/BOOT-INF/classes/]"); this.launcher.launch(new String[0]); waitFor("Hello World"); @@ -236,7 +236,7 @@ void testUserSpecifiedJarPathWithDot() throws Exception { System.setProperty("loader.path", "./jars/app.jar"); System.setProperty("loader.main", "demo.Application"); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(this.launcher, "paths")).hasToString("[jars/app.jar]"); + assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[jars/app.jar]"); this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -246,7 +246,7 @@ void testUserSpecifiedClassLoader() throws Exception { System.setProperty("loader.path", "jars/app.jar"); System.setProperty("loader.classLoader", URLClassLoader.class.getName()); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(this.launcher, "paths")).hasToString("[jars/app.jar]"); + assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[jars/app.jar]"); this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -256,7 +256,7 @@ void testUserSpecifiedClassPathOrder() throws Exception { System.setProperty("loader.path", "more-jars/app.jar,jars/app.jar"); System.setProperty("loader.classLoader", URLClassLoader.class.getName()); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(this.launcher, "paths")) + assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")) .hasToString("[more-jars/app.jar, jars/app.jar]"); this.launcher.launch(new String[0]); waitFor("Hello Other World"); @@ -325,8 +325,8 @@ void testLoadPathCustomizedUsingManifest() throws Exception { manifest.write(manifestStream); } this.launcher = new PropertiesLauncher(); - assertThat((List) ReflectionTestUtils.getField(this.launcher, "paths")).containsExactly("/foo.jar", - "/bar/"); + assertThat((List) ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")) + .containsExactly("/foo.jar", "/bar/"); } @Test From 59de56d66abd65d8fd09447146c0d501021a623c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Tue, 21 Jul 2026 15:11:38 +0200 Subject: [PATCH 2/2] Polish "Fix nested archive paths logging in PropertiesLauncher" See gh-50968 --- .../loader/launch/PropertiesLauncher.java | 10 +++--- .../launch/PropertiesLauncherTests.java | 32 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/loader/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/PropertiesLauncher.java b/loader/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/PropertiesLauncher.java index eddebc7e102f..a88c86ce055a 100644 --- a/loader/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/PropertiesLauncher.java +++ b/loader/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/PropertiesLauncher.java @@ -289,11 +289,9 @@ private void addToSystemProperties() { } } - private List getPaths() throws Exception { + private List resolvePaths() throws Exception { String path = getProperty(PATH); - List paths = (path != null) ? parsePathsProperty(path) : Collections.emptyList(); - debug.log("Nested archive paths: %s", paths); - return paths; + return (path != null) ? parsePathsProperty(path) : Collections.emptyList(); } private List parsePathsProperty(String commaSeparatedPaths) { @@ -467,7 +465,9 @@ private static String capitalize(String str) { @Override protected Set getClassPathUrls() throws Exception { Set urls = new LinkedHashSet<>(); - for (String path : getPaths()) { + List paths = resolvePaths(); + debug.log("Nested archive paths: %s", paths); + for (String path : paths) { path = cleanupPath(handleUrl(path)); urls.addAll(getClassPathUrlsForPath(path)); } diff --git a/loader/spring-boot-loader/src/test/java/org/springframework/boot/loader/launch/PropertiesLauncherTests.java b/loader/spring-boot-loader/src/test/java/org/springframework/boot/loader/launch/PropertiesLauncherTests.java index d434c8ec1b96..403031e803b5 100644 --- a/loader/spring-boot-loader/src/test/java/org/springframework/boot/loader/launch/PropertiesLauncherTests.java +++ b/loader/spring-boot-loader/src/test/java/org/springframework/boot/loader/launch/PropertiesLauncherTests.java @@ -127,7 +127,7 @@ void testUserSpecifiedConfigName() throws Exception { System.setProperty("loader.config.name", "foo"); this.launcher = new PropertiesLauncher(); assertThat(this.launcher.getMainClass()).isEqualTo("my.Application"); - assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[etc/]"); + assertThat(resolvedPaths()).containsExactly("etc/"); } @Test @@ -141,14 +141,14 @@ void testRootOfClasspathFirst() throws Exception { void testUserSpecifiedDotPath() throws Exception { System.setProperty("loader.path", "."); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[.]"); + assertThat(resolvedPaths()).containsExactly("."); } @Test void testUserSpecifiedSlashPath() throws Exception { System.setProperty("loader.path", "jars/"); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[jars/]"); + assertThat(resolvedPaths()).containsExactly("jars/"); Set urls = this.launcher.getClassPathUrls(); assertThat(urls).areExactly(1, endingWith("app.jar")); } @@ -158,7 +158,7 @@ void testUserSpecifiedWildcardPath() throws Exception { System.setProperty("loader.path", "jars/*"); System.setProperty("loader.main", "demo.Application"); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[jars/]"); + assertThat(resolvedPaths()).containsExactly("jars/"); this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -168,7 +168,7 @@ void testUserSpecifiedJarPath() throws Exception { System.setProperty("loader.path", "jars/app.jar"); System.setProperty("loader.main", "demo.Application"); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[jars/app.jar]"); + assertThat(resolvedPaths()).containsExactly("jars/app.jar"); this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -177,8 +177,7 @@ void testUserSpecifiedJarPath() throws Exception { void testUserSpecifiedRootOfJarPath() throws Exception { System.setProperty("loader.path", "jar:file:./src/test/resources/nested-jars/app.jar!/"); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")) - .hasToString("[jar:file:./src/test/resources/nested-jars/app.jar!/]"); + assertThat(resolvedPaths()).containsExactly("jar:file:./src/test/resources/nested-jars/app.jar!/"); Set urls = this.launcher.getClassPathUrls(); assertThat(urls).areExactly(1, endingWith("foo.jar!/")); assertThat(urls).areExactly(1, endingWith("app.jar!/")); @@ -216,8 +215,7 @@ void testUserSpecifiedNestedJarPath() throws Exception { System.setProperty("loader.path", "nested-jars/nested-jar-app.jar!/BOOT-INF/classes/"); System.setProperty("loader.main", "demo.Application"); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")) - .hasToString("[nested-jars/nested-jar-app.jar!/BOOT-INF/classes/]"); + assertThat(resolvedPaths()).containsExactly("nested-jars/nested-jar-app.jar!/BOOT-INF/classes/"); this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -236,7 +234,7 @@ void testUserSpecifiedJarPathWithDot() throws Exception { System.setProperty("loader.path", "./jars/app.jar"); System.setProperty("loader.main", "demo.Application"); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[jars/app.jar]"); + assertThat(resolvedPaths()).containsExactly("jars/app.jar"); this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -246,7 +244,7 @@ void testUserSpecifiedClassLoader() throws Exception { System.setProperty("loader.path", "jars/app.jar"); System.setProperty("loader.classLoader", URLClassLoader.class.getName()); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")).hasToString("[jars/app.jar]"); + assertThat(resolvedPaths()).containsExactly("jars/app.jar"); this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -256,8 +254,7 @@ void testUserSpecifiedClassPathOrder() throws Exception { System.setProperty("loader.path", "more-jars/app.jar,jars/app.jar"); System.setProperty("loader.classLoader", URLClassLoader.class.getName()); this.launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")) - .hasToString("[more-jars/app.jar, jars/app.jar]"); + assertThat(resolvedPaths()).containsExactly("more-jars/app.jar", "jars/app.jar"); this.launcher.launch(new String[0]); waitFor("Hello Other World"); } @@ -309,7 +306,7 @@ void testSystemPropertiesSet() throws Exception { void testArgsEnhanced() throws Exception { System.setProperty("loader.args", "foo"); this.launcher = new PropertiesLauncher(); - assertThat(Arrays.asList(this.launcher.getArgs("bar"))).hasToString("[foo, bar]"); + assertThat(Arrays.asList(this.launcher.getArgs("bar"))).containsExactly("foo", "bar"); } @Test @@ -325,8 +322,7 @@ void testLoadPathCustomizedUsingManifest() throws Exception { manifest.write(manifestStream); } this.launcher = new PropertiesLauncher(); - assertThat((List) ReflectionTestUtils.invokeMethod(this.launcher, "getPaths")) - .containsExactly("/foo.jar", "/bar/"); + assertThat(resolvedPaths()).containsExactly("/foo.jar", "/bar/"); } @Test @@ -447,6 +443,10 @@ private List getExpectedFilesWithExtraLibs(File parent) { return expected; } + private List resolvedPaths() { + return ReflectionTestUtils.invokeMethod(this.launcher, "resolvePaths"); + } + private Condition endingWith(String value) { return new Condition<>() {