The build.gradle.kts I use is as follows

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.springframework.boot.buildpack.platform.build.PullPolicy
import org.springframework.boot.gradle.tasks.bundling.BootBuildImage
import java.io.RandomAccessFile
import java.nio.file.Files

plugins {
    id("java")
    id("org.springframework.boot") version "3.2.1"
    id("io.spring.dependency-management") version "1.1.4"
    id("org.hibernate.orm") version "6.3.1.Final"
    id("org.graalvm.buildtools.native") version "0.9.28"
    kotlin("jvm") version "1.9.20"
    kotlin("plugin.spring") version "1.9.20"
    kotlin("plugin.jpa") version "1.9.20"
    kotlin("plugin.allopen") version "1.9.20"
}

java {
    sourceCompatibility = JavaVersion.VERSION_21
}

repositories {
    maven { setUrl("https://maven.aliyun.com/repository/central") }
    maven { setUrl("https://maven.aliyun.com/repository/jcenter") }
    maven { setUrl("https://maven.aliyun.com/repository/google") }
    maven { setUrl("https://maven.aliyun.com/repository/public") }
    maven { setUrl("https://jitpack.io") }
    mavenCentral()
    google()
}

allOpen {
    annotation("jakarta.persistence.Entity")
    annotation("jakarta.persistence.Embeddable")
    annotation("jakarta.persistence.MappedSuperclass")
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.springframework.boot:spring-boot-starter-mail")
    implementation("org.springframework.boot:spring-boot-starter-validation")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.security:spring-security-crypto")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.springframework.boot:spring-boot-configuration-processor")
    runtimeOnly("com.h2database:h2")
    runtimeOnly("io.micrometer:micrometer-registry-prometheus")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

hibernate {
    enhancement {
        enableAssociationManagement.set(true)
    }
}


tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs += "-Xjsr305=strict"
        jvmTarget = "21"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

When using the following code to create a file or folder in the image built using bootBuildImage, the folder is garbled.

      val fileDir = File(parentFileDir, dir)

        if (log.isDebugEnabled) {
            log.debug("创建文件夹: ${fileDir.invariantSeparatorsPath}")
        }

        fileDir.mkdirs()

The following is the log of the program running

2023-12-28 14:05:32 2023-12-28T06:05:32.255Z DEBUG 1 --- [mcat-handler-24] c.s.q.service.impl.FilesServiceImpl      : 创建文件夹:/workspace/data/files/ac8d35a6-b0aa-4fa2-8951-5cf409bce5fa/测试

However, the actually created folder is displayed as follows on windows

SpringBoot When the image built using bootBuildImage creates files or folders with Chinese names at runtime, their names will be garbled.

Displayed as follows on linux

SpringBoot When the image built using bootBuildImage creates files or folders with Chinese names at runtime, their names will be garbled.

This proves that there is a problem with the build product generated by bootBuildImage. I have used nativeRun to test and found that there is no such problem. The running basic image generated by bootBuildImage should have a problem with Chinese garbled file names.

Comment From: dmikusa

Can you try this https://paketo.io/docs/howto/configuration/#configuring-locale?

Your situation is slightly different, doing work at build time, but you still are going to need to set a locale.

Comment From: Lorwell

I can't find the place to set the runtime mirror environment variable。

I only found one configuration environment. Here is my example. I'm not sure if it works properly.

    docker {
        environment.get()["LANG"] = "en_US.utf8"
    }

Because I see that the annotations configured for this property are used by the build image, I don't know whether the build run image or the build run time image is used.

/**
     * Returns the environment that will be used when building the image.
     * @return the environment
     */

Comment From: dmikusa

When you add an env variable into your Gradle config file, it'll be set at build time only. If you need it to be set a runtime you have two options:

  1. Set it at runtime using your container orchestrator. i.e. docker run -e LANG='en_US.utf8' ...
  2. Embed it into the generated image.

It's a little more config to get set up, but I'd recommend 2.) so it's set consistently on the image.

Comment From: Lorwell

I tried adding environment variables at runtime

 docker run -d -p 8080:8080 --env LANG=en_US.utf8  demo

Specify running BPE environment variables when building

environment.put("BPE_LANG", "en_US.utf8")

Through the log, you can see that the environment variables have taken effect.

    [creator]     Paketo Buildpack for Environment Variables 4.5.6
    [creator]       https://github.com/paketo-buildpacks/environment-variables
    [creator]       Launch Configuration:
    [creator]         $BPE_<NAME>            prepend value to $NAME, delimiting with OS path list separator
    [creator]         $BPE_APPEND_<NAME>     append value to $NAME
    [creator]         $BPE_DEFAULT_<NAME>    set default value for $NAME
    [creator]         $BPE_DELIM_<NAME>      set delimeter to use when appending or prepending to $NAME
    [creator]         $BPE_OVERRIDE_<NAME>   set $NAME to value
    [creator]         $BPE_PREPEND_<NAME>    prepend value to $NAME
    [creator]       Environment Variables: Contributing to layer
    [creator]         Writing env.launch/LANG

Unfortunately, the problem of garbled file names has not been resolved.

Comment From: dmikusa

Try docker run -it --entrypoint launcher demo locale. If you have built the image with BPE_LANG set then you should see it reflected in the output of locale.

Ex:

> docker run -it --entrypoint launcher apps/maven locale
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Setting Active Processor Count to 10
Calculating JVM memory based on 7089436K available memory
For more information on this calculation, see https://paketo.io/docs/reference/java-reference/#memory-calculator
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx6695373K -XX:MaxMetaspaceSize=86862K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 7089436K, Thread Count: 50, Loaded Class Count: 12922, Headroom: 0%)
Enabling Java Native Memory Tracking
Adding 137 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
LANG=en_US.utf8
LANGUAGE=
LC_CTYPE="en_US.utf8"
LC_NUMERIC="en_US.utf8"
LC_TIME="en_US.utf8"
LC_COLLATE="en_US.utf8"
LC_MONETARY="en_US.utf8"
LC_MESSAGES="en_US.utf8"
LC_PAPER="en_US.utf8"
LC_NAME="en_US.utf8"
LC_ADDRESS="en_US.utf8"
LC_TELEPHONE="en_US.utf8"
LC_MEASUREMENT="en_US.utf8"
LC_IDENTIFICATION="en_US.utf8"
LC_ALL=

You might also try setting JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8. If you set up the env variables as shown in the previous link, the JVM should pick up the right file encoding automatically. Since it doesn't seem like it is, you could set it directly with this option.

I believe the problem here is two-fold:

  1. As documented in the link I sent previously, the image Paketo uses doesn't set a locale.
  2. In Java before Java 18 (18+ defaults to utf-8), the default charset is determined by the locale settings. Since we don't set one, it defaults to POSIX which doesn't support the characters you're trying to write.

Once the file is written correctly, the other thing you need is to have a tool that can read it correctly. I'm not sure how you are validating that the file is written correctly, but that tool would also need to be using utf-8 or you can see garbled output also.

Comment From: Lorwell

I found the problem that caused Chinese file names to be written with garbled characters. The reason is that this configuration sun.jnu.encoding is the default configuration used. The file.encoding configuration defaults to UTF-8. When I set ·sun.jnu.encoding=UTF-8, the written Chinese file name is normal, but when reading, the previous display of ?? becomes ������

This makes me very confused. The LANG setting has taken effect and it is indeed LANG=en_US.utf8, because this problem does not exist when I execute nativeRun under the Windows system. Is the encoding of file names under Linux fixed? GBK?

Hope to get your answer

Comment From: Lorwell

I think I have solved this problem. The problem is that when native-compile is compiled, it also needs to set LANG=en_US.utf8, otherwise the compiled localized executable file will produce garbled characters when reading the Chinese file name.

This is a bold guess on my part, but after I set it up like this, the problem was solved.

Comment From: dmikusa

Thanks for sharing your solution!

Comment From: admintertar

@Lorwell Excuse me, can you print Chinese logs without garbled characters

Comment From: Lorwell

@Lorwell Excuse me, can you print Chinese logs without garbled characters

Yes, I can output Chinese characters on the console normally without making any changes.

Comment From: Lorwell

@Lorwell Excuse me, can you print Chinese logs without garbled characters

In the end, I did not use the image construction provided by springboot, but encapsulated a build library myself to facilitate myself to do some customized functions. I provide it for your reference.

https://github.com/Lorwell/graalvm-native-images-/tree/master/graalvm21_ubuntu

Comment From: admintertar

请问,你能打印没有乱码的中文日志吗

最后我没有使用springboot提供的镜像构造,而是自己封装了一个构建库,方便自己做一些自定义功能。我提供它供您参考。

https://github.com/Lorwell/graalvm-native-images-/tree/master/graalvm21_ubuntu

Thank you. I'll try it first.

Comment From: admintertar

Can you help me try using Chinese fuzzy query to see if there will be any errors?

39355

Comment From: Lorwell

Can you help me try using Chinese fuzzy query to see if there will be any errors? #39355

I answered under your question