8350703: Add standard system property stdin.encoding

Reviewed-by: naoto, alanb
This commit is contained in:
Stuart Marks 2025-04-25 16:32:42 +00:00
parent 77f5a24648
commit 15f42e348d
7 changed files with 53 additions and 25 deletions

View File

@ -116,15 +116,23 @@ public final class System {
/**
* The "standard" input stream. This stream is already
* open and ready to supply input data. Typically this stream
* open and ready to supply input data. This stream
* corresponds to keyboard input or another input source specified by
* the host environment or user. In case this stream is wrapped
* in a {@link java.io.InputStreamReader}, {@link Console#charset()}
* should be used for the charset, or consider using
* {@link Console#reader()}.
* the host environment or user. Applications should use the encoding
* specified by the {@link ##stdin.encoding stdin.encoding} property
* to convert input bytes to character data.
*
* @see Console#charset()
* @see Console#reader()
* @apiNote
* The typical approach to read character data is to wrap {@code System.in}
* within an {@link java.io.InputStreamReader InputStreamReader} or other object
* that handles character encoding. After this is done, subsequent reading should
* use only the wrapper object; operating directly on {@code System.in} results
* in unspecified behavior.
* <p>
* For handling interactive input, consider using {@link Console}.
*
* @see Console
* @see ##stdin.encoding stdin.encoding
*/
public static final InputStream in = null;
@ -575,17 +583,22 @@ public final class System {
* <tr><th scope="row">{@systemProperty user.dir}</th>
* <td>User's current working directory</td></tr>
* <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>
* <td>Character encoding name derived from the host environment and
* the user's settings. Setting this system property on the command line
* has no effect.</td></tr>
* <tr><th scope="row">{@systemProperty stdin.encoding}</th>
* <td>Character encoding name for {@link System#in System.in}.
* The Java runtime can be started with the system property set to {@code UTF-8}.
* Starting it with the property set to another value results in unspecified behavior.
* <tr><th scope="row">{@systemProperty stdout.encoding}</th>
* <td>Character encoding name for {@link System#out System.out} and
* {@link System#console() System.console()}.
* 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.
* The Java runtime can be started with the system property set to {@code UTF-8}.
* Starting it with the property set to another value results in unspecified 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.
* The Java runtime can be started with the system property set to {@code UTF-8}.
* Starting it with the property set to another value results in unspecified behavior.
* </tbody>
* </table>
* <p>
@ -639,7 +652,7 @@ public final class System {
* the value {@code COMPAT} then the value is replaced with the
* value of the {@code native.encoding} property during startup.
* Setting the property to a value other than {@code UTF-8} or
* {@code COMPAT} leads to unspecified behavior.
* {@code COMPAT} results in unspecified behavior.
* </td></tr>
* </tbody>
* </table>

View File

@ -88,9 +88,12 @@ public final class SystemProps {
put(props, "file.encoding", nativeEncoding);
}
// "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".
// Encoding properties for stdin, stdout, and stderr. For stdout and stderr,
// check "sun.stdout.encoding" and "sun.stderr.encoding" properties for backward
// compatibility reasons before falling back to the "native.encoding" property.
putIfAbsent(props, "stdin.encoding",
raw.propDefault(Raw._stdin_encoding_NDX));
putIfAbsent(props, "stdin.encoding", nativeEncoding);
putIfAbsent(props, "stdout.encoding", props.getOrDefault("sun.stdout.encoding",
raw.propDefault(Raw._stdout_encoding_NDX)));
putIfAbsent(props, "stdout.encoding", nativeEncoding);
@ -241,7 +244,8 @@ public final class SystemProps {
@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 _stderr_encoding_NDX = 1 + _socksProxyPort_NDX;
@Native private static final int _stdout_encoding_NDX = 1 + _stderr_encoding_NDX;
@Native private static final int _stdin_encoding_NDX = 1 + _stderr_encoding_NDX;
@Native private static final int _stdout_encoding_NDX = 1 + _stdin_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;

View File

@ -154,6 +154,7 @@ Java_jdk_internal_util_SystemProps_00024Raw_platformProperties(JNIEnv *env, jcla
PUTPROP(propArray, _sun_jnu_encoding_NDX, sprops->sun_jnu_encoding);
/* encodings for standard streams, may be NULL */
PUTPROP(propArray, _stdin_encoding_NDX, sprops->stdin_encoding);
PUTPROP(propArray, _stdout_encoding_NDX, sprops->stdout_encoding);
PUTPROP(propArray, _stderr_encoding_NDX, sprops->stderr_encoding);

View File

@ -65,6 +65,7 @@ typedef struct {
char *display_variant;
char *encoding; /* always set non-NULL by platform code */
char *sun_jnu_encoding; /* always set non-NULL by platform code */
char *stdin_encoding;
char *stdout_encoding;
char *stderr_encoding;

View File

@ -464,6 +464,9 @@ GetJavaProperties(JNIEnv *env)
sprops.sun_jnu_encoding = sprops.encoding;
#endif
if (isatty(STDIN_FILENO) == 1) {
sprops.stdin_encoding = sprops.encoding;
}
if (isatty(STDOUT_FILENO) == 1) {
sprops.stdout_encoding = sprops.encoding;
}

View File

@ -634,7 +634,7 @@ GetJavaProperties(JNIEnv* env)
LCID userDefaultUILCID = MAKELCID(userDefaultUILang, SORTIDFROMLCID(userDefaultLCID));
{
HANDLE hStdOutErr;
HANDLE hStdHandle;
// Windows UI Language selection list only cares "language"
// information of the UI Language. For example, the list
@ -677,14 +677,19 @@ GetJavaProperties(JNIEnv* env)
sprops.sun_jnu_encoding = "MS950_HKSCS";
}
hStdOutErr = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOutErr != INVALID_HANDLE_VALUE &&
GetFileType(hStdOutErr) == FILE_TYPE_CHAR) {
hStdHandle = GetStdHandle(STD_INPUT_HANDLE);
if (hStdHandle != INVALID_HANDLE_VALUE &&
GetFileType(hStdHandle) == FILE_TYPE_CHAR) {
sprops.stdin_encoding = getConsoleEncoding(FALSE);
}
hStdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdHandle != INVALID_HANDLE_VALUE &&
GetFileType(hStdHandle) == FILE_TYPE_CHAR) {
sprops.stdout_encoding = getConsoleEncoding(TRUE);
}
hStdOutErr = GetStdHandle(STD_ERROR_HANDLE);
if (hStdOutErr != INVALID_HANDLE_VALUE &&
GetFileType(hStdOutErr) == FILE_TYPE_CHAR) {
hStdHandle = GetStdHandle(STD_ERROR_HANDLE);
if (hStdHandle != INVALID_HANDLE_VALUE &&
GetFileType(hStdHandle) == FILE_TYPE_CHAR) {
if (sprops.stdout_encoding != NULL)
sprops.stderr_encoding = sprops.stdout_encoding;
else

View File

@ -81,6 +81,7 @@ public class PropertyTest {
{"java.runtime.version"},
{"java.runtime.name"},
{"native.encoding"},
{"stdin.encoding"},
{"stdout.encoding"},
{"stderr.encoding"},
};