There's two things at play here, as far as I know.
The encoding used by the terminal.
The encoding used by Java when printing to the standard output and error streams.
When a Java application is launched from a terminal it should be able to pick up/inherit the terminal's output encoding. However, when not launched from a terminal you may have to tell Java which encodings to use for its standard output and error streams, otherwise it will use the platform's defaults. With modern versions of Java (I believe 18+), you can do that with stdout.encoding and stderr.encoding system properties.
Examples (Windows 10/11)
Here's what worked for me on Windows 10/11 with CMD, PowerShell Core, and Git Bash. The following sample project was used with Java 24.0.1 and Maven 3.9.9.
The POM uses the exec-maven-plugin to execute the sample application. There are two executions: exec:java@app and exec:exec@app-forked. The first will execute the application in the same process as Maven and the second will fork the application in its own process. This is to show that how the Java application is launched affects the encoding it uses for its standard output and error streams.
In the CMD, PowerShell Core, and Git Bash examples below, the exec:exec@app-forked execution will always result in Hello, World! ? being printed instead of Hello, World! 🙂, regardless of encoding. At least, it did in my case. To have it print Hello, World! 🙂 when the terminal's encoding is UTF-8, uncomment the -Dstdout.encoding-UTF-8 argument in the execution's configuration.
Note I had the MAVEN_OPTS environment variable set to:
--sun-misc-unsafe-memory-access=allow --enable-native-access=ALL-UNNAMED
To avoid some warnings emitted by Maven's runtime when executing on Java 24.
All commands and their outputs are copy-pasted directly from the terminal (with some user-specific information omitted).
Sample Project
The POM and Java source files are saved with UTF-8 encoding.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>app</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>MyApp 🙂</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>24</maven.compiler.release>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.5.1</version>
<executions>
<!-- exec:java@app -->
<execution>
<id>app</id>
<configuration>
<mainClass>com.example.app.Main</mainClass>
</configuration>
</execution>
<!-- exec:exec@app-forked -->
<execution>
<id>app-forked</id>
<configuration>
<executable>java</executable>
<arguments>
<!-- <argument>-Dstdout.encoding=UTF-8</argument> -->
<argument>-cp</argument>
<classpath/>
<argument>com.example.app.Main</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Main.java:
package com.example.app;
public class Main {
public static void main(String[] args) {
System.out.println("Hello, World! 🙂");
}
}
Command Prompt (CMD)
Used Windows Terminal.
Default Encoding
C:\...\emoji-test> chcp
Active code page: 437
C:\...\emoji-test> mvn compile exec:java@app exec:exec@app-forked
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------< com.example:app >---------------------------
[INFO] Building MyApp ? 0.1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ app ---
[INFO] skip non existing resourceDirectory C:\...\emoji-test\src\main\resources
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ app ---
[INFO] Nothing to compile - all classes are up to date.
[INFO]
[INFO] --- exec:3.5.1:java (app) @ app ---
Hello, World! ?
[INFO]
[INFO] --- exec:3.5.1:exec (app-forked) @ app ---
Hello, World! ?
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.248 s
[INFO] Finished at: 2025-07-01T18:57:45-06:00
[INFO] ------------------------------------------------------------------------
UTF-8 Encoding
C:\...\emoji-test> chcp 65001
Active code page: 65001
C:\...\emoji-test> mvn compile exec:java@app exec:exec@app-forked
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------< com.example:app >---------------------------
[INFO] Building MyApp 🙂 0.1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ app ---
[INFO] skip non existing resourceDirectory C:\...\emoji-test\src\main\resources
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ app ---
[INFO] Nothing to compile - all classes are up to date.
[INFO]
[INFO] --- exec:3.5.1:java (app) @ app ---
Hello, World! 🙂
[INFO]
[INFO] --- exec:3.5.1:exec (app-forked) @ app ---
Hello, World! ?
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.112 s
[INFO] Finished at: 2025-07-01T19:00:56-06:00
[INFO] ------------------------------------------------------------------------
PowerShell Core 7.5.2
Used Windows Terminal.
Default Encoding
PS C:\...\emoji-test> chcp
Active code page: 437
PS C:\...\emoji-test> [Console]::OutputEncoding
IsSingleByte : True
EncodingName : OEM United States
WebName : ibm437
HeaderName : ibm437
BodyName : ibm437
Preamble :
WindowsCodePage :
IsBrowserDisplay :
IsBrowserSave :
IsMailNewsDisplay :
IsMailNewsSave :
EncoderFallback : System.Text.InternalEncoderBestFitFallback
DecoderFallback : System.Text.InternalDecoderBestFitFallback
IsReadOnly : False
CodePage : 437
PS C:\...\emoji-test> mvn compile exec:java@app exec:exec@app-forked
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------< com.example:app >---------------------------
[INFO] Building MyApp ? 0.1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ app ---
[INFO] skip non existing resourceDirectory C:\...\emoji-test\src\main\resources
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ app ---
[INFO] Nothing to compile - all classes are up to date.
[INFO]
[INFO] --- exec:3.5.1:java (app) @ app ---
Hello, World! ?
[INFO]
[INFO] --- exec:3.5.1:exec (app-forked) @ app ---
Hello, World! ?
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.304 s
[INFO] Finished at: 2025-07-01T19:11:47-06:00
[INFO] ------------------------------------------------------------------------
UTF-8 Encoding
PS C:\...\emoji-test> chcp 65001
Active code page: 65001
PS C:\...\emoji-test> [Console]::OutputEncoding = [Text.Encoding]::UTF8
PS C:\...\emoji-test> mvn compile exec:java@app exec:exec@app-forked
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------< com.example:app >---------------------------
[INFO] Building MyApp 🙂 0.1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ app ---
[INFO] skip non existing resourceDirectory C:\...\emoji-test\src\main\resources
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ app ---
[INFO] Nothing to compile - all classes are up to date.
[INFO]
[INFO] --- exec:3.5.1:java (app) @ app ---
Hello, World! 🙂
[INFO]
[INFO] --- exec:3.5.1:exec (app-forked) @ app ---
Hello, World! ?
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.098 s
[INFO] Finished at: 2025-07-01T19:13:27-06:00
[INFO] ------------------------------------------------------------------------
Note both the code page and [Console]::OutputEncoding were set to UTF-8.
Git Bash
Used Git Bash installed with Git version 2.50.0.windows.2.
First, I followed this answer to set the locale encodings in the terminal's options. That leads to the following output:
user@host MINGW64 /.../emoji-test
$ locale
LANG=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="C.UTF-8"
LC_TIME="C.UTF-8"
LC_COLLATE="C.UTF-8"
LC_MONETARY="C.UTF-8"
LC_MESSAGES="C.UTF-8"
LC_ALL=
I'm not sure if that was necessary.
Second, I followed this answer (to the same question). It mentioned chcp.com, which seems to be the same as chcp used previously.
Default Encoding
user@host MINGW64 /.../emoji-test
$ chcp.com
Active code page: 437
user@host MINGW64 /.../emoji-test
$ mvn compile exec:java@app exec:exec@app-forked
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------< com.example:app >---------------------------
[INFO] Building MyApp ? 0.1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ app ---
[INFO] skip non existing resourceDirectory C:\...\src\main\resources
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ app ---
[INFO] Nothing to compile - all classes are up to date.
[INFO]
[INFO] --- exec:3.5.1:java (app) @ app ---
Hello, World! ?
[INFO]
[INFO] --- exec:3.5.1:exec (app-forked) @ app ---
Hello, World! ?
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.409 s
[INFO] Finished at: 2025-07-01T19:25:54-06:00
[INFO] ------------------------------------------------------------------------
Setting LANG to C.UTF-8 or en_US.UTF-8 didn't help.
UTF-8 Encoding
user@host MINGW64 /.../emoji-test
$ chcp.com 65001
Active code page: 65001
user@host MINGW64 /.../emoji-test
$ mvn compile exec:java@app exec:exec@app-forked
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------< com.example:app >---------------------------
[INFO] Building MyApp 🙂 0.1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ app ---
[INFO] skip non existing resourceDirectory C:\...\emoji-test\src\main\resources
[INFO]
[INFO] --- compiler:3.13.0:compile (default-compile) @ app ---
[INFO] Nothing to compile - all classes are up to date.
[INFO]
[INFO] --- exec:3.5.1:java (app) @ app ---
Hello, World! 🙂
[INFO]
[INFO] --- exec:3.5.1:exec (app-forked) @ app ---
Hello, World! ?
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.263 s
[INFO] Finished at: 2025-07-01T19:28:44-06:00
[INFO] ------------------------------------------------------------------------
Though note in the terminal the 🙂 emoji had no color.
Remarks
Setting the active code page with chcp seems to be the common denominator. Though [Console]::OutputEncoding also had to be set for PowerShell Core.
I don't know if there's a system-wide way to set the default code page. For PowerShell you can create a profile script that sets the code page and output encoding. For Git Bash I believe you can add the config to your .bashrc file. Not sure about CMD.
Perhaps https://superuser.com/questions/269818/change-default-code-page-of-windows-console-to-utf-8 can help here.
[Console]::InputEncoding = [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding[Console]::OutputEncoding = [Text.Encoding]::UTF8for PowerShell Core and doingchcp 65001for CMD led toBuilding MyApp 😊 0.1.0-SNAPSHOTbeing printed in both cases.≡ƒÖéin the MS-DOS CP437 character set), which is the UTF-8 sequence for your emoji, code point 1f642.MAVEN_OPTSstopped working when trying it in a new window; not sure what I did differently).