Skip to content

Commit

Permalink
8283620: System.out does not use the encoding/charset specified in th…
Browse files Browse the repository at this point in the history
…e Javadoc

Reviewed-by: alanb
  • Loading branch information
naotoj committed Apr 26, 2022
1 parent 20a132d commit 03bcf7b
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 33 deletions.
4 changes: 2 additions & 2 deletions src/java.base/share/classes/java/io/Console.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -579,7 +579,7 @@ public int read(char[] cbuf, int offset, int length)
if (istty) {
String csname = encoding();
if (csname == null) {
csname = GetPropertyAction.privilegedGetProperty("sun.stdout.encoding");
csname = GetPropertyAction.privilegedGetProperty("stdout.encoding");
}
if (csname != null) {
cs = Charset.forName(csname, null);
Expand Down
26 changes: 17 additions & 9 deletions src/java.base/share/classes/java/lang/System.java
Expand Up @@ -134,7 +134,7 @@ private System() {
* specified by the host environment or user. The encoding used
* in the conversion from characters to bytes is equivalent to
* {@link Console#charset()} if the {@code Console} exists,
* {@link Charset#defaultCharset()} otherwise.
* <a href="#stdout.encoding">stdout.encoding</a> otherwise.
* <p>
* For simple stand-alone Java applications, a typical way to write
* a line of output data is:
Expand All @@ -155,7 +155,7 @@ private System() {
* @see java.io.PrintStream#println(java.lang.Object)
* @see java.io.PrintStream#println(java.lang.String)
* @see Console#charset()
* @see Charset#defaultCharset()
* @see <a href="#stdout.encoding">stdout.encoding</a>
*/
public static final PrintStream out = null;

Expand All @@ -172,10 +172,10 @@ private System() {
* destination that is typically not continuously monitored.
* The encoding used in the conversion from characters to bytes is
* equivalent to {@link Console#charset()} if the {@code Console}
* exists, {@link Charset#defaultCharset()} otherwise.
* exists, <a href="#stderr.encoding">stderr.encoding</a> otherwise.
*
* @see Console#charset()
* @see Charset#defaultCharset()
* @see <a href="#stderr.encoding">stderr.encoding</a>
*/
public static final PrintStream err = null;

Expand Down Expand Up @@ -768,6 +768,14 @@ public static native void arraycopy(Object src, int srcPos,
* <tr><th scope="row">{@systemProperty native.encoding}</th>
* <td>Character encoding name derived from the host environment and/or
* the user's settings. Setting this system property has no effect.</td></tr>
* <tr><th scope="row">{@systemProperty stdout.encoding}</th>
* <td>Character encoding name for {@link System#out System.out}.
* The Java runtime can be started with the system property set to {@code UTF-8},
* starting it with the property set to another value leads to undefined behavior.
* <tr><th scope="row">{@systemProperty stderr.encoding}</th>
* <td>Character encoding name for {@link System#err System.err}.
* The Java runtime can be started with the system property set to {@code UTF-8},
* starting it with the property set to another value leads to undefined behavior.
* </tbody>
* </table>
* <p>
Expand Down Expand Up @@ -2144,11 +2152,11 @@ private static void initPhase1() {
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
setIn0(new BufferedInputStream(fdIn));
// sun.stdout/err.encoding are set when the VM is associated with the terminal,
// thus they are equivalent to Console.charset(), otherwise the encoding
// defaults to native.encoding
setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding", StaticProperty.nativeEncoding())));
setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding", StaticProperty.nativeEncoding())));
// stdout/err.encoding are set when the VM is associated with the terminal,
// thus they are equivalent to Console.charset(), otherwise the encodings
// of those properties default to native.encoding
setOut0(newPrintStream(fdOut, props.getProperty("stdout.encoding")));
setErr0(newPrintStream(fdErr, props.getProperty("stderr.encoding")));

// Setup Java signal handlers for HUP, TERM, and INT (where available).
Terminator.setup();
Expand Down
20 changes: 14 additions & 6 deletions src/java.base/share/classes/jdk/internal/util/SystemProps.java
Expand Up @@ -77,6 +77,16 @@ public static Map<String, String> initProperties() {
putIfAbsent(props, "file.encoding", fileEncoding);
}

// "stdout/err.encoding", prepared for System.out/err. For compatibility
// purposes, substitute them with "sun.*" if they don't exist. If "sun.*" aren't
// available either, fall back to "native.encoding".
putIfAbsent(props, "stdout.encoding", props.getOrDefault("sun.stdout.encoding",
raw.propDefault(Raw._stdout_encoding_NDX)));
putIfAbsent(props, "stdout.encoding", nativeEncoding);
putIfAbsent(props, "stderr.encoding", props.getOrDefault("sun.stderr.encoding",
raw.propDefault(Raw._stderr_encoding_NDX)));
putIfAbsent(props, "stderr.encoding", nativeEncoding);

// Use platform values if not overridden by a commandline -Dkey=value
// In no particular order
putIfAbsent(props, "os.name", raw.propDefault(Raw._os_name_NDX));
Expand All @@ -100,8 +110,6 @@ public static Map<String, String> initProperties() {
putIfAbsent(props, "sun.arch.abi", raw.propDefault(Raw._sun_arch_abi_NDX));
putIfAbsent(props, "sun.arch.data.model", raw.propDefault(Raw._sun_arch_data_model_NDX));
putIfAbsent(props, "sun.os.patch.level", raw.propDefault(Raw._sun_os_patch_level_NDX));
putIfAbsent(props, "sun.stdout.encoding", raw.propDefault(Raw._sun_stdout_encoding_NDX));
putIfAbsent(props, "sun.stderr.encoding", raw.propDefault(Raw._sun_stderr_encoding_NDX));
putIfAbsent(props, "sun.io.unicode.encoding", raw.propDefault(Raw._sun_io_unicode_encoding_NDX));
putIfAbsent(props, "sun.cpu.isalist", raw.propDefault(Raw._sun_cpu_isalist_NDX));
putIfAbsent(props, "sun.cpu.endian", raw.propDefault(Raw._sun_cpu_endian_NDX));
Expand Down Expand Up @@ -218,16 +226,16 @@ public static class Raw {
@Native private static final int _socksNonProxyHosts_NDX = 1 + _path_separator_NDX;
@Native private static final int _socksProxyHost_NDX = 1 + _socksNonProxyHosts_NDX;
@Native private static final int _socksProxyPort_NDX = 1 + _socksProxyHost_NDX;
@Native private static final int _sun_arch_abi_NDX = 1 + _socksProxyPort_NDX;
@Native private static final int _stderr_encoding_NDX = 1 + _socksProxyPort_NDX;
@Native private static final int _stdout_encoding_NDX = 1 + _stderr_encoding_NDX;
@Native private static final int _sun_arch_abi_NDX = 1 + _stdout_encoding_NDX;
@Native private static final int _sun_arch_data_model_NDX = 1 + _sun_arch_abi_NDX;
@Native private static final int _sun_cpu_endian_NDX = 1 + _sun_arch_data_model_NDX;
@Native private static final int _sun_cpu_isalist_NDX = 1 + _sun_cpu_endian_NDX;
@Native private static final int _sun_io_unicode_encoding_NDX = 1 + _sun_cpu_isalist_NDX;
@Native private static final int _sun_jnu_encoding_NDX = 1 + _sun_io_unicode_encoding_NDX;
@Native private static final int _sun_os_patch_level_NDX = 1 + _sun_jnu_encoding_NDX;
@Native private static final int _sun_stderr_encoding_NDX = 1 + _sun_os_patch_level_NDX;
@Native private static final int _sun_stdout_encoding_NDX = 1 + _sun_stderr_encoding_NDX;
@Native private static final int _user_dir_NDX = 1 + _sun_stdout_encoding_NDX;
@Native private static final int _user_dir_NDX = 1 + _sun_os_patch_level_NDX;
@Native private static final int _user_home_NDX = 1 + _user_dir_NDX;
@Native private static final int _user_name_NDX = 1 + _user_home_NDX;
@Native private static final int FIXED_LENGTH = 1 + _user_name_NDX;
Expand Down
6 changes: 3 additions & 3 deletions src/java.base/share/native/libjava/System.c
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -160,8 +160,8 @@ Java_jdk_internal_util_SystemProps_00024Raw_platformProperties(JNIEnv *env, jcla
/*
* file encoding for stdout and stderr
*/
PUTPROP(propArray, _sun_stdout_encoding_NDX, sprops->sun_stdout_encoding);
PUTPROP(propArray, _sun_stderr_encoding_NDX, sprops->sun_stderr_encoding);
PUTPROP(propArray, _stdout_encoding_NDX, sprops->stdout_encoding);
PUTPROP(propArray, _stderr_encoding_NDX, sprops->stderr_encoding);

/* unicode_encoding specifies the default endianness */
PUTPROP(propArray, _sun_io_unicode_encoding_NDX, sprops->unicode_encoding);
Expand Down
6 changes: 3 additions & 3 deletions src/java.base/share/native/libjava/java_props.h
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -65,8 +65,8 @@ typedef struct {
char *display_variant;
char *encoding;
char *sun_jnu_encoding;
char *sun_stdout_encoding;
char *sun_stderr_encoding;
char *stdout_encoding;
char *stderr_encoding;

char *unicode_encoding; /* The default endianness of unicode
i.e. UnicodeBig or UnicodeLittle */
Expand Down
6 changes: 3 additions & 3 deletions src/java.base/unix/native/libjava/java_props_md.c
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -455,10 +455,10 @@ GetJavaProperties(JNIEnv *env)
sprops.sun_jnu_encoding = sprops.encoding;
#endif
if (isatty(STDOUT_FILENO) == 1) {
sprops.sun_stdout_encoding = sprops.encoding;
sprops.stdout_encoding = sprops.encoding;
}
if (isatty(STDERR_FILENO) == 1) {
sprops.sun_stderr_encoding = sprops.encoding;
sprops.stderr_encoding = sprops.encoding;
}

#ifdef _ALLBSD_SOURCE
Expand Down
10 changes: 5 additions & 5 deletions src/java.base/windows/native/libjava/java_props_md.c
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -709,15 +709,15 @@ GetJavaProperties(JNIEnv* env)
hStdOutErr = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOutErr != INVALID_HANDLE_VALUE &&
GetFileType(hStdOutErr) == FILE_TYPE_CHAR) {
sprops.sun_stdout_encoding = getConsoleEncoding();
sprops.stdout_encoding = getConsoleEncoding();
}
hStdOutErr = GetStdHandle(STD_ERROR_HANDLE);
if (hStdOutErr != INVALID_HANDLE_VALUE &&
GetFileType(hStdOutErr) == FILE_TYPE_CHAR) {
if (sprops.sun_stdout_encoding != NULL)
sprops.sun_stderr_encoding = sprops.sun_stdout_encoding;
if (sprops.stdout_encoding != NULL)
sprops.stderr_encoding = sprops.stdout_encoding;
else
sprops.sun_stderr_encoding = getConsoleEncoding();
sprops.stderr_encoding = getConsoleEncoding();
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions test/jdk/java/lang/System/PropertyTest.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -40,7 +40,7 @@

/*
* @test
* @bug 4463345 4244670 8030781 8265989
* @bug 4463345 4244670 8030781 8265989 8283620
* @summary Simple test of System getProperty, setProperty, clearProperty,
* getProperties, and setProperties
* @run testng/othervm PropertyTest
Expand Down Expand Up @@ -81,6 +81,8 @@ static Object[][] requiredProperties() {
{"java.runtime.version"},
{"java.runtime.name"},
{"native.encoding"},
{"stdout.encoding"},
{"stderr.encoding"},
};
}

Expand Down

1 comment on commit 03bcf7b

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.