System.out和最终对象内联

时间:2011-11-14 19:44:35

标签: java

我们都知道javac在编译时内联常量,当只重新编译应用程序的各个部分时,这会导致一些有趣的问题,这里的每个人都知道通常的解决方案(使得javac不理解它实际上是编译时间)常数)

但是如果我们查看oracle JDK的System.class中的代码,我们会看到以下内容:

public final static PrintStream out = null;

因此,假设out是由JVM初始化中的反射或其他机制设置的。但这导致了一个问题:为什么不在这里进行内联? (至少我在使用System.out.println()时从未得到空指针异常)。

javac是特殊情况,那个场景还是实际上是由语言规范处理的?

2 个答案:

答案 0 :(得分:1)

我的JDK代码说out = nullInputStream()并对该方法发表评论:

/**
 * 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().
 */

initializeSystemClass()调用setOut0(..) native,可能会绕final进行调用。 System.setOut(..)的工作方式相同。

答案 1 :(得分:1)

static final构造有多种结果。文字可能会被内联 例如static final int xxx = 1,因为它很清楚,但例如static final int xxx = returnOne()可能不是。

原始类型和字符串只能用文字替换,其他所有对象都不能。最后但并非最不重要的是System.out/in违反了JLS(一旦最终字段被初始化,它总是包含相同的值。)。

阻止内联的几种方法:static final String xxx="xxx".intern();static final int yyy=123+return0();,因为评估可能只在运行时执行,javac将生成GETFIELD而不是BIPUSH(对于int)。