Quazi Irfan
Quazi Irfan

Reputation: 2589

How System.in of type InputStream is initialized?

I know that, in java, abstract class can only be referenced but not initialized. InputStream is an abstract class, and in the System class I noticed the following declaration,

static InputStream in;

So if we want the code System.in.read() to work, variable in needs to be initialized.

My question is how java does that? If InputStream is abstract, some other subclass should have extend it. Which class is that by default?

Upvotes: 1

Views: 1726

Answers (3)

Luckily, it is easy to check the type of object System.in refers to:

System.out.println(System.in.getClass().getName());

prints ( for me ):

java.io.BufferedInputStream

so it's a BufferedInputStream. What is it wrapping? Well,

Field field = FilterInputStream.class.getDeclaredField("in");
field.setAccessible(true);   
System.out.println(field.get(System.in).getClass().getName());

prints (again, for me):

java.io.FileInputStream

So System.in is a FileInputStream wrapped in a BufferedInputStream. This makes sense, if you consider that most operating systems treat the console the same way as a file. In fact, this FileInputStream reads from the "file" referred to by FileDescriptor.in.

By searching for references to FileDescriptor.in, I found the code where System.in is initialized: in the private static method System.initializeSystemClass:

FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
setIn0(new BufferedInputStream(fdIn));
setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));

initializeSystemClass is probably called by native code, as there seem to be no references to it.

Upvotes: 5

Stephen C
Stephen C

Reputation: 718826

There is some black magic that happens behind the scenes during JVM bootstrap to initialize in to the correct value.

For example, in Java 8 it is done by a private method called initializeSystemClass(). The javadoc comment says:

"Initialize the system class. Called after thread initialization."

Read the source code for the gory details. They could vary from one Java version to the next ... though they don't appear to have changed between Java 6 and Java 8.

Notes:

  1. The actual setting of System.in,out,err is done by native methods. These native methods are also used by the System.set{In,Out,Err} methods.

  2. In Java 6 through Java 8, the in field is initialized to a BufferedInputStream that wraps a FileInputStream. Interestingly, the input stream is typically not for a "file" ... in the sense of an object in the / a file system.

Upvotes: 4

Tarik
Tarik

Reputation: 5021

The declaration in the System class is the following:

public final static InputStream in = null;

Please take a look at the javadocs:

The "standard" input stream. This stream is already open and ready to supply input data. Typically this stream corresponds to keyboard input or another input source specified by the host environment or user.

It means that System.in is initialized by the Java runtime when a JVM starts up. Regarding your question:

If InputStream is abstract, some other subclass should have extend it. Which class is that by default?

Many classes extends the InputStream class, like: FileInputStream, ObjectInputStream, ...

Upvotes: -1

Related Questions