如何更改System.out的值?

时间:2013-08-14 21:47:42

标签: java constants system.out

在研究java.lang.System类的实现时,我发现了这个:

public final static PrintStream out = null;

仅从该定义,我可以看出System.out的值始终为null。但是,它在程序启动时初始化(使用JVM自动调用的System.initializeSystemClass()方法),我可以使用执行安全检查的System.setOut更改其值,然后将调用委托给setOut0方法是一种native方法,用于更改System.out的值。 为什么我可以更改System.out的值,即使它已声明为final

2 个答案:

答案 0 :(得分:6)

这是API中的历史瑕疵。 JLS实际上special-cases System.{in,out,err},如果今天设计API,可能会有不同的声明。

这种奇怪的行为在实践中通过忽略System的Java定义来实现。 System是核心类之一(以及RuntimeObject,系统ClassLoader和其他一些),它们是Java程序与外部环境的接口。 JVM。为了执行它们的任务,它们必须由JRE以(大部分)本机代码提供,在这种情况下,System的实际C代码忽略了Java API声明字段{{1}的事实。 }}

答案 1 :(得分:1)

  

我问如何通过本机代码更改最终字段的值。

它的工作原理与其他任何本机代码更改字段值的方式相同。编译器在编译时检测到final变量的修改。除了通过调用Field.set()启动的显式检查之外,没有运行时检查。在任何时候都没有任何运行时内存保护或其他任何涉及,即使它是,它将由JVM而不是操作系统完成。本机代码不必关心字段上的元数据,它只能在内存中设置字节。它完全超出了Java编译器的编译时间检查的范围。

final字段的本机代码修改在整个程序中甚至可能不是可见,因为允许编译器在final字段上执行优化。这就是nullPrintStream()位与Java 7之前的关系。