diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index ae1c65b9f935d..5e28b9ce95b7c 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -191,8 +191,9 @@ private System() { */ public static final PrintStream err = null; - // Holder for the initial value of `in`, set within `initPhase1()`. - private static InputStream initialIn; + // Initial values of System.in and System.err, set in initPhase1(). + private static @Stable InputStream initialIn; + private static @Stable PrintStream initialErr; // indicates if a security manager is possible private static final int NEVER = 1; @@ -355,9 +356,6 @@ private static class CallersHolder { = Collections.synchronizedMap(new WeakHashMap<>()); } - // Remember initial System.err. setSecurityManager() warning goes here - private static volatile @Stable PrintStream initialErrStream; - private static URL codeSource(Class clazz) { PrivilegedAction pa = clazz::getProtectionDomain; @SuppressWarnings("removal") @@ -417,7 +415,7 @@ public static void setSecurityManager(@SuppressWarnings("removal") SecurityManag } else { source = callerClass.getName() + " (" + url + ")"; } - initialErrStream.printf(""" + initialErr.printf(""" WARNING: A terminally deprecated method in java.lang.System has been called WARNING: System::setSecurityManager has been called by %s WARNING: Please consider reporting this to the maintainers of %s @@ -2200,7 +2198,8 @@ private static void initPhase1() { // 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"))); + initialErr = newPrintStream(fdErr, props.getProperty("stderr.encoding")); + setErr0(initialErr); // Setup Java signal handlers for HUP, TERM, and INT (where available). Terminator.setup(); @@ -2406,8 +2405,6 @@ private static void initPhase3() { notSupportedJnuEncoding); } - initialErrStream = System.err; - // initializing the system class loader VM.initLevel(3); @@ -2598,6 +2595,10 @@ public InputStream initialSystemIn() { return initialIn; } + public PrintStream initialSystemErr() { + return initialErr; + } + public void setCause(Throwable t, Throwable cause) { t.setCause(cause); } diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java index af7ff2e4aa255..c31e745cd89a6 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java @@ -26,6 +26,7 @@ package jdk.internal.access; import java.io.InputStream; +import java.io.PrintStream; import java.lang.annotation.Annotation; import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; @@ -401,6 +402,11 @@ public interface JavaLangAccess { */ InputStream initialSystemIn(); + /** + * Returns the initial value of System.err. + */ + PrintStream initialSystemErr(); + /** * Encodes ASCII codepoints as possible from the source array into * the destination byte array, assuming that the encoding is ASCII diff --git a/src/java.base/share/classes/jdk/internal/misc/VM.java b/src/java.base/share/classes/jdk/internal/misc/VM.java index 9b51cfad458a8..de6f011fe8ffd 100644 --- a/src/java.base/share/classes/jdk/internal/misc/VM.java +++ b/src/java.base/share/classes/jdk/internal/misc/VM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -27,6 +27,7 @@ import static java.lang.Thread.State.*; +import java.io.PrintStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -496,4 +497,11 @@ private static class BufferPoolsHolder { public static List getBufferPools() { return BufferPoolsHolder.BUFFER_POOLS; } + + /** + * Return the initial value of System.err that was set during VM initialization. + */ + public static PrintStream initialErr() { + return SharedSecrets.getJavaLangAccess().initialSystemErr(); + } }