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

Reviewed-by: asotona, cstein, liach
This commit is contained in:
Jan Lahoda 2025-05-27 09:49:26 +00:00
parent b9db99d7f7
commit 9c191cc0fa
3 changed files with 32 additions and 15 deletions

View File

@ -37,6 +37,7 @@ import java.io.PrintStream;
import java.io.Writer;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
@ -159,10 +160,15 @@ class ConsoleIOContext extends IOContext {
boolean allowExecTerminal = !OSUtils.IS_WINDOWS &&
!OSUtils.IS_LINUX &&
!OSUtils.IS_OSX;
terminal = TerminalBuilder.builder().exec(allowExecTerminal).inputStreamWrapper(in -> {
input.setInputStream(in);
return nonBlockingInput;
}).nativeSignals(false).build();
terminal = TerminalBuilder.builder()
.exec(allowExecTerminal)
.inputStreamWrapper(in -> {
input.setInputStream(in);
return nonBlockingInput;
})
.nativeSignals(false)
.encoding(System.getProperty("stdin.encoding"))
.build();
useComplexDeprecationHighlight = !OSUtils.IS_WINDOWS;
}
this.allowIncompleteInputs = allowIncompleteInputs;
@ -968,6 +974,9 @@ class ConsoleIOContext extends IOContext {
}
}
private static final Charset stdinCharset =
Charset.forName(System.getProperty("stdin.encoding"),
Charset.defaultCharset());
private String pendingLine;
private int pendingLinePointer;
private byte[] pendingBytes;
@ -990,7 +999,7 @@ class ConsoleIOContext extends IOContext {
pendingLinePointer--;
}
}
pendingBytes = dataToConvert.toString().getBytes();
pendingBytes = dataToConvert.toString().getBytes(stdinCharset);
pendingBytesPointer = 0;
}
return pendingBytes[pendingBytesPointer++];

View File

@ -48,9 +48,8 @@ import com.sun.jdi.ThreadReference;
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.VirtualMachine;
import java.io.PrintStream;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import jdk.jshell.JShellConsole;
import jdk.jshell.execution.JdiDefaultExecutionControl.JdiStarter.TargetDescription;
import jdk.jshell.spi.ExecutionControl;
@ -71,7 +70,12 @@ import jdk.jshell.execution.impl.ConsoleImpl.ConsoleOutputStream;
*/
public class JdiDefaultExecutionControl extends JdiExecutionControl {
private static final int SHUTDOWN_TIMEOUT = 1; //1 second
private static final Duration SHUTDOWN_TIMEOUT = Duration.ofSeconds(1);
private static final List<String> FORWARD_SYSTEM_PROPERTIES = List.of(
"stderr.encoding",
"stdin.encoding",
"stdout.encoding"
);
private VirtualMachine vm;
private Process process;
@ -105,11 +109,15 @@ public class JdiDefaultExecutionControl extends JdiExecutionControl {
int port = listener.getLocalPort();
Optional<JShellConsole> console = env.console();
String consoleModule = console.isPresent() ? "jdk.jshell" : "java.base";
List<String> augmentedremoteVMOptions =
Stream.concat(env.extraRemoteVMOptions().stream(),
//disable System.console():
List.of("-Djdk.console=" + consoleModule).stream())
.toList();
List<String> augmentedremoteVMOptions = new ArrayList<>();
//the stdin/out/err.encoding properties are always defined, and can be copied:
FORWARD_SYSTEM_PROPERTIES.forEach(
prop -> augmentedremoteVMOptions.add("-D" + prop + "=" +
System.getProperty(prop)));
augmentedremoteVMOptions.addAll(env.extraRemoteVMOptions());
augmentedremoteVMOptions.add("-Djdk.console=" + consoleModule);
ExecutionEnv augmentedEnv = new ExecutionEnv() {
@Override
public InputStream userIn() {
@ -279,7 +287,7 @@ public class JdiDefaultExecutionControl extends JdiExecutionControl {
if (remoteProcess != null) {
try {
remoteProcess.waitFor(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS);
remoteProcess.waitFor(SHUTDOWN_TIMEOUT);
} catch (InterruptedException ex) {
debug(ex, "waitFor remote");
}

View File

@ -35,7 +35,7 @@
* @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
* @build Compiler UITesting
* @compile InputUITest.java
* @run testng InputUITest
* @run testng/othervm -Dstderr.encoding=UTF-8 -Dstdin.encoding=UTF-8 -Dstdout.encoding=UTF-8 InputUITest
*/
import java.util.function.Function;