Created
April 18, 2025 22:00
-
-
Save basilevs/cb1a0d3b48b7fd17bdced693d5082508 to your computer and use it in GitHub Desktop.
https://bugs.openjdk.org/browse/JDK-8025883 reproducer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.basilevs.example.flush; | |
import java.io.BufferedOutputStream; | |
import java.io.ByteArrayOutputStream; | |
import java.io.IOException; | |
import java.io.PrintStream; | |
import java.nio.charset.Charset; | |
import java.nio.charset.StandardCharsets; | |
import java.util.Objects; | |
/// Demonstrates that PrintStream does not check for new line character despite documentation mentioning it | |
public class AutoFlushShouldNotFlushTooOften { | |
private static final Charset CHARSET = StandardCharsets.UTF_8; | |
private final static String TEST_DATA = "Text without EOL. It is not supposed to flush"; | |
private final static int BUFFER_SIZE = 10_000; // large enough to to fit test data | |
public static void main(String[] args) throws IOException, InterruptedException { | |
ByteArrayOutputStream bytes = new ByteArrayOutputStream(); | |
try ( PrintStream output = new PrintStream( | |
new BufferedOutputStream(bytes, BUFFER_SIZE), true, CHARSET)) { | |
/// Documentation for autoFlush = true says: | |
/// > The output buffer will be flushed whenever a byte array is written, one of the println methods is invoked, or a newline character or byte ('\n') is written | |
/// This implies that newline character is significant. | |
/// However, the flush happens always, even if data has no line breaks. | |
/// This leads to a minor performance loss, as flush happens on every character, not on every line | |
/// Arguably, autoFlush should be false for performance, but documentation is still misleading. | |
/// # Entrypoints | |
/// - java.io.PrintStream.implWrite(String) - does unconditional charOut.flushBuffer() before content check is done | |
/// - it leads to java.io.PrintStream.implWrite(byte[], int, int) which has no content check | |
/// - java.io.PrintStream.implWrite(String) then checks content for new line character, but flush is already done, so the check is redundant | |
output.print(TEST_DATA); // PrintStream.print() is not expected to flush until a new line character | |
Thread.sleep(1000); | |
assertContent("", bytes); | |
} | |
assertContent(TEST_DATA, bytes); // PrintStream.close() is expected to flush | |
} | |
static void assertContent(String expectedContent, ByteArrayOutputStream flushable) throws IOException { | |
String flushedContent = new String(flushable.toByteArray(), CHARSET); | |
if (!Objects.equals(expectedContent, flushedContent)) { | |
throw new AssertionError("No content is supposed to be flushed, but received: " + flushedContent); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment