Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mvn spring-boot:run fails on Windows with "Could Not Find or Load Main Class" when path contains non-ASCII characters #43051

Closed
muellerarmin opened this issue Nov 6, 2024 · 8 comments
Assignees
Labels
type: regression A regression from a previous release
Milestone

Comments

@muellerarmin
Copy link

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
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Nov 6, 2024
@wilkinsona
Copy link
Member

wilkinsona commented Nov 6, 2024

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.

@wilkinsona wilkinsona added the status: waiting-for-feedback We need additional information before we can continue label Nov 6, 2024
@muellerarmin
Copy link
Author

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)?

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 6, 2024
@philwebb
Copy link
Member

philwebb commented Nov 7, 2024

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

@philwebb philwebb added the for: team-attention An issue we'd like other members of the team to review label Nov 7, 2024
@mhalbritter
Copy link
Contributor

mhalbritter commented Nov 7, 2024

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.

@mhalbritter mhalbritter self-assigned this Nov 7, 2024
@mhalbritter mhalbritter changed the title Special characters in source path prevent application start - Could Not Find or Load Main Class @argument file doesn't use the correct encoding Nov 7, 2024
@mhalbritter mhalbritter added this to the 3.3.x milestone Nov 7, 2024
@mhalbritter mhalbritter added type: bug A general bug and removed for: team-attention An issue we'd like other members of the team to review status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided labels Nov 7, 2024
@mhalbritter
Copy link
Contributor

mhalbritter commented Nov 7, 2024

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.

@mhalbritter
Copy link
Contributor

mhalbritter commented Nov 7, 2024

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().

@mhalbritter
Copy link
Contributor

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

@mhalbritter
Copy link
Contributor

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

@wilkinsona wilkinsona changed the title @argument file doesn't use the correct encoding mvn spring-boot:run fails on Windows with "Could Not Find or Load Main Class" when path contains non-ASCII characters Nov 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

5 participants