PrintStream object out is initialized by null, how we call method on it?

萝らか妹 提交于 2019-11-28 09:18:20

JVM calls the private static void initializeSystemClass() method which initializes it.

See these two lines of code :

setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true));

These are the two native methods :

private static native void setOut0(PrintStream out);
private static native void setErr0(PrintStream err);

There is a nice article on it.

The explanation is in the comments:

/**
 * The following two methods exist because in, out, and err must be
 * initialized to null.  The compiler, however, cannot be permitted to
 * inline access to them, since they are later set to more sensible values
 * by initializeSystemClass().
 */

And initializeSystemClass() uses native methods to initialize the standard streams to non-null values. Native code can reinitialize variables that are declared final.

There is a getter and setter for out object.

When System class get initialized, it calls its initializeSystemClass() method, here is the code:

FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));

In this code setOut0() is a native function implemented in System.c:

JNIEXPORT void JNICALL
Java_java_lang_System_setOut0(JNIEnv *env, jclass cla, jobject stream)
{
    jfieldID fid =
        (*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;");
    if (fid == 0)
        return;
    (*env)->SetStaticObjectField(env,cla,fid,stream);
}

This is a standard JNI code that sets System.out to the argument passed to it, this method calls the native method setOut0() which sets the out variable to the appropriate value.

System.out is final, it means it cannot be set to something else in initializeSystemClass() but using native code it is possible to modify a final variable.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!