8

Let us try to redirect standard error for java:

java -version 2> ~/error.txt

error.txt is populated with version.

Let us try to redirect standard output:

java -version > ~/output.txt

output.txt is empty.

Why does java binary print normal output to error stream?

sleske
  • 81,358
  • 34
  • 189
  • 227
Kshitiz Sharma
  • 17,947
  • 26
  • 98
  • 169

2 Answers2

12

According to the Java documentation:

-showversion

Displays version information and continues execution of the application. This option is equivalent to the -version option except that the latter instructs the JVM to exit after displaying version information.

-version

Displays version information and then exits. This option is equivalent to the -showversion option except that the latter does not instruct the JVM to exit after displaying version information.

Now consider Wikipedia's definition of stderr:

Standard error is another output stream typically used by programs to output error messages or diagnostics.

Most POSIX-centric tools prescribe a very careful specification for their stdout stream, so the tool's output can be piped elsewhere. Stderr is much less prescribed, and used liberally for logging and errors.

With -showversion, Java allows the version information to be printed adjacent to a running application. However, if the version information were printed to stdout, it would be indistinguishable from the normal application output that could accompany it, forcing you to scan for and remove that line of output yourself. Of course, with -version instead of -showversion, the version string very likely is the intended output, but keeping consistency is a decent end in itself.

For what it's worth, printing requested metadata to stderr vs stdout is something of an open question, so there's little in terms of "standard practice" aside from behavior documented per-application.

To work around this, just redirect stderr to stdout:

VERSION=$(java -version 2>&1)
Community
  • 1
  • 1
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • 2
    On OpenJdk 11.0.1 there is 4 options: `-version`, `--version`, `-showversion` and `--showversion`. Both `version`and `showversion`does the same effect, but with only one dash it output as error, with two dash both output as normal and can be stored into variables. If you want to get, for some reason, error output and store it into variable you can do like this: > Invoke-Expression "java -version" -ErrorVariable javaVaraible java : openjdk version "11.0.1" 2018-10-16 ... > $javaVaraible java : openjdk version "11.0.1" 2018-10-16 ... – Thibault Nov 12 '18 at 10:33
2

Seems like its a bug or just an inconsistency the java command has compared to many other commands in UNIX send version output to stdout:

mvn -v > ~/output.txt # works as expected

There is a bug for it but this was closed. Probably Oracle can't fix the problem since it might cause for problems for systems that expect it to behave this way.

Andrew
  • 1,269
  • 9
  • 17