Why Does 'Java -Version' Go to Stderr

Why does java.util.logging.Logger print to stderr?

By default, the logger outputs log records of level INFO and above (i.e., INFO, WARNING and SEVERE) to standard error stream (System.err).

Source: www3.ntu.edu.sg/home/ehchua/programming/java/JavaLogging.html

How do you not output to stderr from a Java app?

You can use: http://docs.oracle.com/javase/6/docs/api/java/lang/System.html#setErr%28java.io.PrintStream%29

Just make some mock up class that does nothing but adheres to the PrintStream interface and you are good to go.

Why do System.err statements get printed first sometimes?

Typically, System.out is a buffered output stream, so text is accumulated before it is flushed to the destination location. This can dramatically improve performance in applications that print large amounts of text, since it minimizes the number of expensive system calls that have to be made. However, it means that text is not always displayed immediately, and may be printed out much later than it was written.

System.err, on the other hand, typically is not buffered because error messages need to get printed immediately. This is slower, but the intuition is that error messages may be time-critical and so the program slowdown may be justified. According to the Javadoc for System.err:

Typically this stream corresponds to display output or another output destination specified by the host environment or user. By convention, this output stream is used to display error messages or other information that should come to the immediate attention of a user even if the principal output stream, the value of the variable out, has been redirected to a file or other destination that is typically not continuously monitored.

(My emphasis)

However, as a result, old data sent to System.out might show up after newer System.err messages, since the old buffered data is flushed later than the message was sent to System.err. For example this sequence of events:

  • "Hello," is buffered to System.out
  • "PANIC" is sent directly to System.err and is printed immediately.
  • " world!" is buffered to System.out, and the buffered data is printed

Would result in the output

PANIC
Hello, world!

Even though Hello was printed to System.out before PANIC was printed to System.err.

Hope this helps!

relations between log levels and stdErr/stdOut

Very briefly:

Loggers are part of a high level logging framework. Logging is much more advanced than standard output streams.

When a process starts up the operating system gives it a stdout and stderr stream which the program may write to. Stdout should be used for information and stderr for error information.

This is much lower level and you can access these streams with the System class:

System.out.println(); // Write to stdout
System.err.println(); // Write to stderr

Why can't my Java program read Perl's STDERR?

getErrorStream does not read the error stream, it just obtains a handle to it. As it's a pipe, if you never actually read it, it will fill up and force the Perl program to block.

You need something like:

Inputstream errors = getErrorStream();
while (errors.read(buffer) > 0) {
SOP buffer;
}

Why does process hang if the parent does not consume stdout/stderr in Java?

Java doesn't do anything in this area. It just uses OS services to create the pipes.

All Unix like OSs and Windows behave the same in this regard: A pipe with a 4K is created between parent and child. When that pipe is full (because one side isn't reading), the writing process blocks.

This is the standard since the inception of pipes. There is not much Java can do.

What you can argue is that the process API in Java is clumsy and doesn't have good defaults like simply connecting child streams to the same stdin/stdout as the parent unless the developer overrides them with something specific.

I think there are two reasons for the current API. First of all, the Java developers (i.e. the guys at Sun/Oracle) know exactly how the process API works and what you need to do. They know so much that it didn't occur to them that the API could be confusing.

The second reason is that there is no good default that will work for the majority. You can't really connect stdin of the parent and the child; if you type something on the console, to which process should the input go?

Similarly, if you connect stdout, the output will go somewhere. If you have a web app, there might be no console or the output might go somewhere where no one will expect it.

You can't even throw an exception when the pipe is full since that can happen during the normal operation as well.

Why use stderr when printf works fine?

It is good practice to redirect all error messages to stderr, while directing regular output to stdout. It is beneficial to do this because anything written to stderr is not buffered, i.e., it is immediately written to the screen so that the user can be warned immediately.

Java: Program stdout and stderr to some sort of handler

By using System.setOut() and System.setErr() you can set standard output and error stream to any PrintStream, and capture everything.

ADDITION:
I don't know if there exist any elegant way to do this, but one way to do so is:

1. Save default output stream

PrintStream defaultOut = System.out;

(System.getOut() would be fun to have though)

2. Redirect System.out to the printstream you want (e.g. any file)

3. Instead of using System.out.println() use your print function, which does following:

print(Object o){

defaultOut.println(o);//Assuming that defaultOut is visible in this function

System.out.println(o);
}

Read an external process's interleaved stdout and stderr exactly as they are written

The comments by John Kugelman pointed my in the right direction. Thank you a lot!

The buffering doesn't happen on the Java side but is the result of piping stdout and stderr to another program. In this case the JVM.

it becomes full buffered. stderr, on the other hand, stays line buffered even when piped.

So we want to change the buffer behavior of the external process call.

I took the script route described in https://unix.stackexchange.com/a/61833/274368.
My code now looks something like this:

String command = "script -q -c \"my-command\" /dev/null";
ProcessBuilder processBuilder = fs.runInShell(command, args.toArray(new String[args.size()]));
processBuilder.directory(workingDirectory);
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
try (BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String message = input.lines().collect(Collectors.joining(System.lineSeparator()));
// ...
}

Where message contains all lines from stderr and stdout in the correct order.



Related Topics



Leave a reply



Submit