【问题标题】:In the System.java source, the standard input, output and error streams are declared final and initialized null?在 System.java 源代码中,标准输入、输出和错误流被声明为 final 并初始化为 null?
【发布时间】:2013-06-12 11:06:25
【问题描述】:
public final static InputStream in = null;
public final static PrintStream out = null;
public final static PrintStream err = null;

但众所周知,这些流默认连接到控制台并且已经打开。 System 类中还有一些方法 setIn()、setOut 和 setErr() 来重定向流。当它们被声明为 final 并设置为初始化值 null 时,这怎么可能?

我编译了以下代码,在调用 println() 时设置了一个断点,并使用 netbeans 进行了调试。我的目标是通过进入源代码来准确确定变量 System.in 何时初始化为标准输出。但是在调用 main 方法时,输出流 out 似乎已经初始化了。

public static void main(String[] args) {
    System.out.println("foo");
}

【问题讨论】:

  • 值得注意的是,final 变量仍然可以被操作,只是只能在编译时阻止操作,特别是通过阻止您使用赋值运算符 (=)。见this question

标签: java stream


【解决方案1】:

这样做是为了防止“黑客攻击”。这些字段只能由调用native 方法的适当设置器更改

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

本机方法可以做任何事情,包括更改最终字段。

【讨论】:

    【解决方案2】:

    它们稍后由原生方法 SetIn0SetOut0SetErr0 设置

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

    initializeSystemClass 方法调用,根据JavaDoc,该方法在线程初始化后调用

    FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
    FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
    FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
    setIn0(new BufferedInputStream(fdIn));
    setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
    setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true));
    

    【讨论】:

    • 我确实在源代码中看到了 setIn0、setOut0 和 setErr0 方法,但我不知道本地方法可以更改最终变量。我可以获得上述 JavaDoc 的链接吗?
    【解决方案3】:

    final 字段不一定是常量。它们仍然可以被操纵,只是在编译时才阻止操纵,特别是通过阻止您使用赋值运算符 (=)。见this questionJLS §17.5.3,具体来说:

    final 字段可以通过反射和其他依赖于实现的方式进行更改。

    这对于反序列化之类的事情是必要的。这也可能导致一些有趣的警告,因为编译器可以在编译时和运行时优化final 字段。上面链接的 JLS 有一个例子。

    【讨论】:

      猜你喜欢
      • 2015-10-22
      • 2021-07-30
      • 2023-03-15
      • 2014-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-25
      • 2013-05-11
      相关资源
      最近更新 更多