在检查 JDK 14 及更高版本中
System
类的初始化时,很明显,标准输入/输出流是通过调用 registerNatives()
方法来设置的,该方法是从静态初始化块调用的,并且本身是本机的。然而,引人注目的是变量out
、in
和err
被定义为static
和final
。由于final
,这些字段需要使用常量值进行显式初始化。最初,它们在班级内设置为 null
。
考虑到它们的初始化可能由本机方法处理,对
null
的显式赋值不会简单地从代码中消失,从逻辑上讲,这部分代码也应该执行。此外,如果我们假设整个过程发生在 <clinit>
方法的幕后,则本机方法将首先完成,然后是分配 null
的字段初始值设定项(例如,查看 out
字段) 。如何有效地覆盖 null
,以及实际的初始化发生在哪里?
此外,如果我们深入研究注释,就会发现该类的初始化在某种程度上与
<clinit>
的常规执行是分开的:
/* Register the natives via the static initializer.
*
* The VM will invoke the initPhase1 method to complete the initialization
* of this class separate from <clinit>.
*/
private static native void registerNatives();
static {
registerNatives();
}
什么是
initPhase1
?这个阶段会发生什么?它到底意味着什么?我实在是太好奇了!提前感谢大家!
在检查 JDK 14 及更高版本中
System
类的初始化时,很明显,标准输入/输出流是通过调用 registerNatives()
方法来设置的,[...]
不,这些不是从
registerNatives()
初始化的。它们在 initPhase1()
方法中初始化,这是一个常规 Java 方法(在 System
类中),在初始化 System
类之后(即在这些字段被设置为null
)。
对
initPhase1()
的调用是在名为 initialize_java_lang_classes
的 C++ 方法中完成的。