Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8356245

stdin.encoding and stdout.encoding in jshell don't respect console code pages

XMLWordPrintable

    • b26
    • 18
    • generic
    • windows_10

      ADDITIONAL SYSTEM INFORMATION :
      openjdk 25-ea 2025-09-16
      OpenJDK Runtime Environment (build 25-ea+21-2530)
      OpenJDK 64-Bit Server VM (build 25-ea+21-2530, mixed mode, sharing)

      Windows 11 24H2

      (Note: stdin.encoding requires the latest EA build 21)

      A DESCRIPTION OF THE PROBLEM :
      Terminals in Windows can change their I/O code pages from the OEM code page by chcp (CMD) or changing the Console.InputEncoding or Console.OutputEncoding properies (in PowerShell/C#).
      By this you can receive or send any Unicode characters from/to external programs.
      The normal java command can recognize such code pages and adjust such properties, but JShell doesn't.
      JShell cannot recognize the change. Such properties are fixed to the string of the OEM code page there.
      This cause character corruption in statements and expressions using System.in, System.out, and IO (Java 25+).

      The current code pages can be obtained by GetConsoleCP or GetConsoleOutputCp functions in Windows API.

      https://learn.microsoft.com/en-us/windows/console/getconsoleoutputcp
      https://learn.microsoft.com/en-us/windows/console/getconsolecp

      TL; DR: Test Case Code does not cause corruption in java command but does in JShell once you change console code pages.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Run `chcp 65001` (CMD) or `[Console]::InputEncoding = [Console]::OutputEncoding = [System.Text.Encoding]::UTF8` (PowerShell)
      2. Run `jshell` (e.g. `jdk-25\bin\jshell`)
      3. Evaluate the following expressions there:

      ```java
      System.getProperty("stdin.encoding")
      System.getProperty("stdout.encoding")
      ```

      4. Run the following commands there:

      ```java
      System.out.println("πŸ‘");
      System.out.println("√2 ÷ 2 = 1 / √2");
      ```

      πŸ‘: Unicode dedicated character
      √ & ÷: non-ASCII characters in OEM code page but not automatically converted to ASCII one (e.g. ¥ in Japanese)

      5: Run the following command and type some non-ASCII string there:

      ```
      (new Scanner(System.in, System.getProperty("stdin.encoding"))).nextLine()
      ```

      -----

      Test Case Code can be run `java path\to\TestCaseCode.java` to prove that this bug does *not* exist in normal programs. Input string can be e.g. `√2 ÷ 2 = 1 / √2πŸ‘` in Shift_JIS / CP437.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      jshell> System.getProperty("stdin.encoding")
      $1 ==> "UTF-8"

      jshell> System.getProperty("stdout.encoding")
      $2 ==> "UTF-8"

      jshell> System.out.println("πŸ‘")
      πŸ‘

      jshell> System.out.println("√2 ÷ 2 = 1 / √2");
      √2 ÷ 2 = 1 / √2

      jshell> (new Scanner(System.in, System.getProperty("stdin.encoding"))).nextLine()
      √2 ÷ 2 = 1 / √2
      $5 ==> "√2 ÷ 2 = 1 / √2"
      ACTUAL -
      Note: an example in Japanese environment

      jshell> System.getProperty("stdin.encoding")
      $1 ==> "MS932"

      jshell> System.getProperty("stdout.encoding")
      $2 ==> "MS932"

      jshell> System.out.println("πŸ‘")
      ?

      jshell> System.out.println("√2 ÷ 2 = 1 / √2");
      οΏ½οΏ½2 οΏ½οΏ½ 2 = 1 / οΏ½οΏ½2

      jshell> (new Scanner(System.in, System.getProperty("stdin.encoding"))).nextLine()
      √2 ÷ 2 = 1 / √2
      $5 ==> "竏�2 οΎƒο½· 2 = 1 / 竏�2"

      ---------- BEGIN SOURCE ----------
      // Correctly outputs as expected unlike in JShell even after you change code pages to UTF-8:
      //
      // stdin: UTF-8
      // stdout: UTF-8
      // πŸ‘
      // √2 ÷ 2 = 1 / √2
      // Input: √2 ÷ 2 = 1 / √2πŸ‘
      // √2 ÷ 2 = 1 / √2πŸ‘
      import java.util.Scanner;

      class Test {
          public static void main(String[] args) {
              System.out.println("stdin: " + System.getProperty("stdin.encoding"));
              System.out.println("stdout: " + System.getProperty("stdout.encoding"));
              System.out.println("πŸ‘");
              System.out.println("√2 ÷ 2 = 1 / √2");
              System.err.print("Input: ");
              System.out.println((new Scanner(System.in, System.getProperty("stdin.encoding"))).nextLine());
          }
      }
      ---------- END SOURCE ----------

            cstein Christian Stein
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: