为什么Java的System.int/out/err值为null?

JAVA 二月 13, 2020

为什么Java的System.int/out/err值为null?

文章字数 1.8k 阅读约需 2 mins. 阅读次数 1000000

例:
System源码中这样写:

1
public final static PrintStream out = null;

System.out是PrintStream类型的变量,引用的是null,还被final修饰为不可更改,为什么在调用PrintStream中的println()方法时没有报错呢?
实际上在System类的开头有静态代码块:

1
2
3
static {
registerNatives();
}

在加载System类的时候先调用了System类中的静态方法registerNatives(),
它在虚拟机里注册System需要使用的一些本地代码,
在System类中这样定义registerNatives()方法:

1
private static native void registerNatives()

也使用了native修饰符,这意味着该方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。
Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。
它会告诉虚拟机到哪些文件中找到相应的实现。In,out,err先初始化为null(防止编译器内联访问它们),然后由initializeSystemClass()方法类使用setInt0,setOut0,setErr0把实际连接到输入输出设备的句柄传给虚拟机并赋值给in,out,err。
因此System类是首先声明了in/out(实际上还有err)静态成员常量,然后在registerNatives()中对其进行赋值,使得能够调用println等方法。

0%