diff --git a/src/java.base/share/classes/java/io/Console.java b/src/java.base/share/classes/java/io/Console.java index 0aa12bdf4c8..8ae4fc00773 100644 --- a/src/java.base/share/classes/java/io/Console.java +++ b/src/java.base/share/classes/java/io/Console.java @@ -34,7 +34,7 @@ import jdk.internal.access.SharedSecrets; import jdk.internal.io.JdkConsoleImpl; import jdk.internal.io.JdkConsoleProvider; import jdk.internal.javac.PreviewFeature; -import jdk.internal.util.StaticProperty; +import sun.nio.cs.UTF_8; import sun.security.action.GetPropertyAction; /** @@ -580,7 +580,8 @@ public sealed class Console implements Flushable permits ProxyingConsole { * the {@code Console}. *

* The returned charset corresponds to the input and output source - * (e.g., keyboard and/or display) specified by the host environment or user. + * (e.g., keyboard and/or display) specified by the host environment or user, + * which defaults to the one based on {@link System##stdout.encoding stdout.encoding}. * It may not necessarily be the same as the default charset returned from * {@link java.nio.charset.Charset#defaultCharset() Charset.defaultCharset()}. * @@ -614,30 +615,11 @@ public sealed class Console implements Flushable permits ProxyingConsole { "Console class itself does not provide implementation"); } - private static native String encoding(); private static final boolean istty = istty(); - static final Charset CHARSET; + static final Charset CHARSET = + Charset.forName(GetPropertyAction.privilegedGetProperty("stdout.encoding"), UTF_8.INSTANCE); + private static final Console cons = instantiateConsole(); static { - Charset cs = null; - - if (istty) { - String csname = encoding(); - if (csname == null) { - csname = GetPropertyAction.privilegedGetProperty("stdout.encoding"); - } - if (csname != null) { - cs = Charset.forName(csname, null); - } - } - if (cs == null) { - cs = Charset.forName(StaticProperty.nativeEncoding(), - Charset.defaultCharset()); - } - - CHARSET = cs; - - cons = instantiateConsole(); - // Set up JavaIOAccess in SharedSecrets SharedSecrets.setJavaIOAccess(new JavaIOAccess() { public Console console() { @@ -689,6 +671,5 @@ public sealed class Console implements Flushable permits ProxyingConsole { return c; } - private static final Console cons; private static native boolean istty(); } diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 930b6b7f611..5b04bca4f44 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -147,8 +147,7 @@ public final class System { * corresponds to display output or another output destination * 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, - * stdout.encoding otherwise. + * {@link ##stdout.encoding stdout.encoding}. *

* For simple stand-alone Java applications, a typical way to write * a line of output data is: @@ -168,8 +167,7 @@ public final class System { * @see java.io.PrintStream#println(long) * @see java.io.PrintStream#println(java.lang.Object) * @see java.io.PrintStream#println(java.lang.String) - * @see Console#charset() - * @see stdout.encoding + * @see ##stdout.encoding stdout.encoding */ public static final PrintStream out = null; @@ -185,11 +183,9 @@ public final class System { * variable {@code out}, has been redirected to a file or other * 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, stderr.encoding otherwise. + * equivalent to {@link ##stderr.encoding stderr.encoding}. * - * @see Console#charset() - * @see stderr.encoding + * @see ##stderr.encoding stderr.encoding */ public static final PrintStream err = null; @@ -788,7 +784,8 @@ public final class System { * Character encoding name derived from the host environment and/or * the user's settings. Setting this system property has no effect. * {@systemProperty stdout.encoding} - * Character encoding name for {@link System#out System.out}. + * 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. * {@systemProperty stderr.encoding} diff --git a/src/java.base/unix/native/libjava/Console_md.c b/src/java.base/unix/native/libjava/Console_md.c index e5b760a1499..1e71ab3a6b2 100644 --- a/src/java.base/unix/native/libjava/Console_md.c +++ b/src/java.base/unix/native/libjava/Console_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -36,9 +36,3 @@ Java_java_io_Console_istty(JNIEnv *env, jclass cls) { return isatty(fileno(stdin)) && isatty(fileno(stdout)); } - -JNIEXPORT jstring JNICALL -Java_java_io_Console_encoding(JNIEnv *env, jclass cls) -{ - return NULL; -} diff --git a/src/java.base/windows/native/libjava/Console_md.c b/src/java.base/windows/native/libjava/Console_md.c index 9423f7d9e31..f73e62f8e26 100644 --- a/src/java.base/windows/native/libjava/Console_md.c +++ b/src/java.base/windows/native/libjava/Console_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -49,17 +49,3 @@ Java_java_io_Console_istty(JNIEnv *env, jclass cls) return JNI_TRUE; } - -JNIEXPORT jstring JNICALL -Java_java_io_Console_encoding(JNIEnv *env, jclass cls) -{ - char buf[64]; - int cp = GetConsoleCP(); - if (cp >= 874 && cp <= 950) - snprintf(buf, sizeof(buf), "ms%d", cp); - else if (cp == 65001) - snprintf(buf, sizeof(buf), "UTF-8"); - else - snprintf(buf, sizeof(buf), "cp%d", cp); - return JNU_NewStringPlatform(env, buf); -} diff --git a/test/jdk/java/io/Console/DefaultCharsetTest.java b/test/jdk/java/io/Console/DefaultCharsetTest.java new file mode 100644 index 00000000000..0b17217e109 --- /dev/null +++ b/test/jdk/java/io/Console/DefaultCharsetTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @test + * @bug 8341975 + * @summary Tests the default charset. It should honor `stdout.encoding` + * which should be the same as System.out.charset() + * @modules jdk.internal.le + * @run junit/othervm -Dstdout.encoding=UTF-8 DefaultCharsetTest + * @run junit/othervm -Dstdout.encoding=ISO-8859-1 DefaultCharsetTest + * @run junit/othervm -Dstdout.encoding=US-ASCII DefaultCharsetTest + * @run junit/othervm -Dstdout.encoding=foo DefaultCharsetTest + * @run junit/othervm DefaultCharsetTest + */ +public class DefaultCharsetTest { + @Test + public void testDefaultCharset() { + var stdoutEncoding = System.getProperty("stdout.encoding"); + var sysoutCharset = System.out.charset(); + var consoleCharset = System.console().charset(); + System.out.println(""" + stdout.encoding = %s + System.out.charset() = %s + System.console().charset() = %s + """.formatted(stdoutEncoding, sysoutCharset.name(), consoleCharset.name())); + assertEquals(consoleCharset, sysoutCharset, + "Charsets for System.out and Console differ for stdout.encoding: %s".formatted(stdoutEncoding)); + } +}