When having special characters in the path where the files are located (e.g. German umlauts (ä,ö,ü) or accents (é, è); example: /c/Users/username/workbench/café/src/main/java/com/organization/test/Application.java), the application will fail at the "attaching agents" stage with the error "Could Not Find or Load Main Class". This behavior starts at Spring Boot 3.3.0 and persists (at least) until 3.3.5. Versions 3.2.11 and previous (I tested versions 3.2.8 to 3.2.11) are not affected.

Steps to recreate: - create a new Spring Boot project (e.g. with initializr) with Spring Boot version 3.3.*, Java 21 - copy it to a path that includes a special character (e.g. to workbench/café/) - try starting it via an IDE or via the console (e.g. via mvn clean compile org.springframework.boot:spring-boot-maven-plugin:run)

Further information: - Java 21 (build 21.0.5+9-LTS-239) - Apache Maven 3.9.9 (8e8579a9e76f7d015ee5ec7bfcdc97d260186937) - Windows 10

Comment From: wilkinsona

As far as I can tell, this is caused by the introduction of an @argument file to avoid path length limits on Windows. The classpath is written into this file as UTF-8 text but Java's then loading it with a different encoding which corrupts some of the paths. Java’s documentation states that "the argument file must contain only ASCII characters or characters in system default encoding that’s ASCII friendly, such as UTF-8" so this should work fine as long as the system default encoding is UTF-8.

I haven't managed to figure how to convince Windows that its default encoding is UTF-8 and that's what the JVM should use by default. Configuring -Djava.encoding=UTF-8 as a JVM argument for spring-boot:run doesn't appear to work, presumably because the args file has already been read. Neither does setting the JAVA_TOOL_OPTIONS environment variable.

I'm far from a Windows expert. @muellerarmin, perhaps you will have more joy in configuring Windows such that Java uses UTF-8 by default without any further configuration. Please give it a try and let us know how it goes.

Comment From: muellerarmin

Thanks for the hints, @wilkinsona. I was able to enforce UTF-8 like this:

Change System Locale to UTF-8 in Windows

  1. Open Control Panel:
  2. Press Win + S to open the search bar, type Control Panel, and open it.
  3. In Control Panel, select Clock and Region, then click on Region.
  4. In the Region dialog, go to the Administrative tab.
  5. Click on Change system locale…
  6. In the Region Settings dialog that opens, you’ll see a checkbox labeled Beta: Use Unicode UTF-8 for worldwide language support. Check this box and click OK.
  7. Restart Your Computer:

Although this helped, I'm not sure if that is the best option, since it forces a system wide encoding change. Maybe a resolution on Spring Boot's side would be better (if possible)?

Comment From: philwebb

I wonder if writing the arg file using Files.writeString(this.path, "\"" + escape(content) + "\"", Charset.defaultCharset()); would work.

Comment From: mhalbritter

That'd be my idea too, @philwebb. Maybe we can improve the argfile situation further by only writing it if the command length exceeds some kind of threshold. Then most of the time no argfile would be used, only if the classpath is really long.

Comment From: mhalbritter

Using Charset.defaultCharset won't work. It's set to UTF-8 even on windows.

System.out.println("java.encoding = " + System.getProperty("java.encoding"));
System.out.println("file.encoding = " + System.getProperty("file.encoding"));
System.out.println("native.encoding = " + System.getProperty("native.encoding"));
System.out.println("Charset = " + Charset.defaultCharset());

prints

java.encoding = null
file.encoding = UTF-8
native.encoding = Cp1252
Charset = UTF-8

on my Windows machine.

The native.encoding property looks interesting. This is set to UTF-8 on my linux machine and to cp1252 (which was the default file encoding for older VMs on Windows). So maybe that's the right one. I'm going to investigate more.

Comment From: mhalbritter

JavaDoc of System.getProperties says:

Character encoding name derived from the host environment and/ or the user's settings. Setting this system property has no effect.

In the JDK itself it's used in java.lang.Process#inputReader(), java.lang.Process#errorReader(), and java.lang.Process#outputWriter().

Comment From: mhalbritter

This seems to work. When using native.encoding, non-ascii characters in the path work fine.

Comment From: mhalbritter

I've pushed something which should fix the issue. When the build is done, you can try with 3.3.6-SNAPSHOT.