8

I read several posts online explaining what System.out.println() is in Java. Most of them go like this:

  • System is a final class in the java.lang package.
  • out is a public static object inside the System class of type PrintStream.
  • println() prints a line of text to the output stream.

My question is when we do System.out.println() in our code, why does it end up writing to the console? This article explains how we can make it write to a file by calling System.setOut(). So my question translates to where is System.setOut() called to redirect its output to the console?

I checked System.setOut()'s source. It makes a call to setOut0() which is a native method. This method is directly called inside the initializeSystemClass() method by passing it fdOut which is a FileOutputStream defined here. I did not find a console output stream passed to setOut0() anywhere, nor did I find a call to the non-native setOut() done anywhere. Is it done somewhere else outside the System class by the JVM while starting execution? If so, can someone point me to it?

7
  • 2
    It doesn't have to be the console, it is the standard output stream of the process. That is normally the console but may well be a file or something else. See en.wikipedia.org/wiki/Standard_streams. Commented Apr 12, 2020 at 8:28
  • is it defined anywhere in code? Commented Apr 12, 2020 at 8:33
  • The fdout actually output to console. I suppose it is FileOutputStream as in Linux/Unix system, io device is also treated as file. Commented Apr 12, 2020 at 8:37
  • 1
    Are you asking "When java starts up, how is the out initially set?" and "From where is it set?" This is how I read your Question, but it seems to me that answers are answering something else. Commented Apr 12, 2020 at 8:45
  • 1
    Does this help? How System.out.println() really works Commented Apr 12, 2020 at 8:49

4 Answers 4

6

My doubt is when we do System.out.println() in our code, why it ends up in writing to console?

In any POSIX compliant shell, each process gets three "standard" streams when the shell starts it:

  • The "standard input" stream is for reading input.
  • The "standard output" stream is for writing ordinary output.
  • The "standard error" stream is for writing error output.

(The same idea is also used in many non-POSIX compliant shells as well.)

For an interactive POSIX shell, the default is for these streams to read from and write to the shell's "console" ... which could be a physical console, but is more likely to be a "terminal emulator" on the user's (ultimate) desktop machine. (Details vary.)

A POSIX shell allows you to redirect the standard streams in various ways; e.g.

$ some-command < file # read stdin from 'file' $ some-command > file # write stdout to 'file' $ some-command 2> file # write stderr to 'file' $ some-command << EOF # read stdin from a 'here' document lines of input ... EOF $ some-command | another # connect stdout for one command to # stdin for the next one in a pipeline 

and so on. If you do this, one or more of the standard streams is NOT connected to the console.

Further reading:


So how does this relate to the question?

When a Java program start, the System.in/out/err streams are connected to the standard input / output / error streams specified by the parent process; typically a shell.

In the case of System.out, that could be the console (however you define that) or it could be a file, or another program or ... /dev/null. But where the output goes is determined by how the JVM was launched.

So, the literal answer is "because that is what the parent process has told the Java program to do".


How internally shell communicates with jvm to set standard input / output in both Windows and Linux?

This is what happens with Linux, UNIX, Mac OSX and similar. (I don't know for Windows ... but I imagine it is similar.)

Suppose that the shell is going to run aaa > bbb.txt.

  1. The parent shell forks a child process ... sharing the parent shell's address space.
  2. The child process closes file descriptor 1 (the standard output file descriptor)
  3. The child process opens "bbb.txt" for writing on file descriptor 1.
  4. The child process execs the "aaa" command, and it becomes the "aaa" command process. The file descriptors 0, 1, and 2 are preserved by the exec call.
  5. The "aaa" command starts ...

When the "aaa" command starts, it finds that file descriptors 0 and 2 (stdin and stderr) refer to the same "file" as the parent shell. File descriptor 1 (stdout) refers to "bbb.txt".

The same thing happens when "aaa" is the java command.

Sign up to request clarification or add additional context in comments.

2 Comments

I tried doing java MyJava abcd. sysout in my java code printed "Hello abcd!!!" on console. When I did java MyJava abcd > textfile.txt, sysout in my java code output "Hello abcd!!!" to textfile.txt. So I got that now. Now am trying to understand: "because that is what the parent process has told the Java program to do". Specifically what exactly "technically" happens when we specify > vs when we dont specify it? That is, how internally shell communicates with jvm to set standard input / output in both Windows and Linux?
@mercury - What are you trying to achieve? You don't need to import anything to use System.out. What does this have to do with this Question + Answer?
1

It doesn't need to. We can redirect to somewhere else. Here is the code to re-direct into the file:

PrintStream output = new PrintStream(new File("output.txt")); System.setOut(output); System.out.println("This will be written to file"); 

By default, the console is the standard output stream (System.in) in Java.

Comments

0

System.out.println does not print to the console, it prints to the standard output stream (System.out is Java's name of the standard output stream). The standard output stream is usually the console, but it doesn't have to be. The Java runtime just wraps the standard output stream of the operating system in a nice Java object.

A non-interactive program often uses a few standard input and output channels: it reads input from the standard input stream, does some operations on it, and produces output on the standard output stream. The standard output stream can be the console, but it can also be piped to the standard input stream of another program or to a file. In the end, the operating system running the programming decides what the standard output stream output to.

For example, in Unix terminals you can do something like:

java -jar your.program.jar > output.txt 

and store the output of your program in a text file, or

java -jar your.program.jar | grep hello 

to only display the lines of the output which contain 'hello'. Only if you don't specify another destination, the standard output stream writes to the console.

Comments

0

The System is the final class present in java.lang package. Out is a static instance inside the System class of type PrintStream. println() is a method present in the PrintStream class. As soon as the System class is loaded into memory at the class initialization phase the JVM will call the Java Native Interface JNI method setOut internally defined in the System.java class and thereafter System.c file is called to do the further things and then written back to object PrintStream which has print overloaded methods.

System class cannot be instantiated since it is singleton and the variable of out is null by default and print methods are available in PrintStream class

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.