在更改System.out 引用之后,进行再次修改时,如果不把之前的OutputStream关闭掉,会不会造成资源的泄露? 从而引发内存问题? 
比如 //①保留系统默认流对象 
PrintStream out = System.out; 
//②然后更改 
System.out = new new PrintStream(); 
//③还原默认outputStream  
System.out = out; 在执行第三步的时候,如果没有对步骤2中System.out流进行关闭操作,会不会产生问题? 有必要调用System.out.close()方法吗? 

解决方案 »

  1.   

    现在开发的系统  是一只运行在服务器端的,如果这样不释放的 会不会造成服务器的崩溃?  比如几个月之后会不会down 掉?
    如果写例子程序肯定不会有问题。
      

  2.   

    JAVA垃圾回收机制会处理这个,但如果想更好的利用资源,最好手动CLOSE。LZ可以根据实际情况决定是否CLOSE。
      

  3.   


    系统是涉及到大文件的操作。 用的是ant提供的一个DemuxOutputStream类,用的是ant-task
      

  4.   

    JAVA垃圾回收机制会处理这个,楼主想自己手动close,也是可以,但要自己写close方法
      

  5.   

    您好,Java垃圾回收是回收没有引用的内存空间吧, 现在的问题据好比用完数据库没有关闭连接的感觉,现在做的系统通过分析jvm,可能某些操作产生了内存泄露。
      

  6.   

    System.out = out; 这个能编译过去? 这个out不是final的么?...偶郁闷咯 从没这么想过..
      

  7.   


    不好意思打错了是System.setOut(out);
      

  8.   

    呵呵  你看错了吧
    lz写的是
    PrintStream out = System.out; 
      

  9.   

    kan bu dong   cainiao
      

  10.   

    import java.io.BufferedOutputStream;
    import java.io.FileDescriptor;
    import java.io.FileOutputStream;
    import java.io.PrintStream;
    public class TestChangeOut {
    public static void main(String [] args) {
    //当前System.out的hashcode
    System.out.println(System.out);
    //关闭当前System的out标准输出流
    System.out.close();
    //这步因上一步的关系无任何输出
    System.out.println("~");
    //FileDescriptor.out 标准输出流的句柄。通常,此文件描述符不是直接使用的,而是通过称为 System.out 的输出流使用的。 
    FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
    PrintStream newOut = new PrintStream(new BufferedOutputStream(fdOut, 128), true);
    //设置新的标准输出流
    System.setOut(newOut);
    //新的System.out的hashcode,与旧的不一样
    System.out.println(System.out);
    }
    }
    看了System类和一些其他的类的源码,发现了一些问题(也许是我没耐心看下去)。比如:
    1.out常量是final的,照理说是无法再改变其引用地址的,实际测试后发现可以改变。
    2.out这个标准控制台输出流实际占多少资源不得而知,但这个不重要,重要的是在这个out被我们更换了新的实例后,旧实例是否当即就被自动close了,这过程里面有包装,甚至还调用了一些非java的本地方法(native)。如果是自动close,那么就表示一个jvm实例同一时间只会拥有一份开启状态的标准输出流实例,那么关不关就无所谓了。
    3.引用论坛某位前辈的解答,close不仅仅是告诉jvm这个流被关闭,也告诉了承载jvm的操作系统这一层,这个流被关闭了,也就是说,当我们忘记close而又不再引用此流的实例,gc确实有可能会清扫此实例,但只要jvm进程不停止,操作系统这一层一直会开启这个流而占用一定的资源。
    一家之言,谨慎采纳。
      

  11.   

    呵呵,System 这个类是非常奇怪,其语法结构已经超出了 Java 语言的范围,比如 out, in, err 都是 final 的,但是使用 setOut 也可以重新赋值。再比如,out, in, err 都是在 initializeSystemClass() 这个 private 的静态方法中赋值的,但是在 System 中也没有任何一个地方调用过这个方法。这些估计都与其内部的 native 方法有关。没必要关掉 System.out 的流,虽然执行 System.out.close() 方法,只是关闭与之相关联的 PrintStream 中的内部属性,但是具体的 System.out 实现是由操作系统实现的,Java 也不可能去关闭掉操作系统的流。这种关闭就好比这样代码的最后一行,没有用。User user = new User();
    user.xxxx
    ....
    user = null;
      

  12.   

    关闭了之后就打不出来了,如我上面的那段代码。结论是,背后原理不得而知,但System.out这个标准输出流确实没必要关闭。
      

  13.   


    没异常么?
    另外 如果将System.out的输出流换成普通的输出流 比如输出到某个文件上 可以不可以呢?
      

  14.   

    不会出异常
    输出到本地文件理论上可以,实际试验后发现真的可以。
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileDescriptor;
    import java.io.FileOutputStream;
    import java.io.PrintStream;
    public class TestChangeOut {
    public static void main(String [] args) throws Exception {
    //当前System.out的hashcode
    System.out.println(System.out);
    //关闭当前System的out标准输出流
    System.out.close();
    //这步因上一步的关系无任何输出
    System.out.println("~");
    //FileDescriptor.out 标准输出流的句柄。通常,此文件描述符不是直接使用的,而是通过称为 System.out 的输出流使用的。 
    //FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
    //换成输出本地的方式也可以
    FileOutputStream fdOut = new FileOutputStream(new File("C:/mytxt.txt"));
    PrintStream newOut = new PrintStream(new BufferedOutputStream(fdOut, 128), true);
    //设置新的标准输出流
    System.setOut(newOut);
    //新的System.out的hashcode,与旧的不一样
    System.out.println(System.out);
    }
    }
      

  15.   

    问题是 转到文件流的时候 如果不关闭掉System.out.close();直接System.setOut();成默认的流 会不会造成文件资源流没有被关闭掉?
    我查了好多地方了 自己也进行了测试,  结论还是无法确定。 
      

  16.   

    如果想把输出到控制台的东西全部改为输出到本地文件中,还是建议自己封装一个方法调用之(当然也要在需要时close),而不是改变System.out
    不过有个奇怪的问题:
    在同一jvm实例(进程)中只要有一个程序改变了System.out,其他程序中是否也被改变?目前我在eclipse中新建一个类,改变System.out,再用无限循环执行,其每次启动后修改前的hashcode都是一致的(eclipse和正在运行的一个java程序分占了两个javaw.exe进程。一个javaw.exe进程就是一个jvm实例?)
      

  17.   

    关于System.out,他是一个显示设备输出流,对其进行close是没有意义的,好像jdk doc上面也说了,其close方法是个空实现,也就是说,你调用了close方法,其实跟不调用没什么区别。
    如果你使用System.setOut,使用了自己的输出流,如果这个流指向网络或者文件系统,那么就要close掉了。
      

  18.   

    JAVA垃圾回收机制会处理这个,但如果想更好的利用资源,最好手动CLOSE。
      

  19.   

    JAVA垃圾回收机制会处理这个,但如果想更好的利用资源,最好手动CLOSE。 LZ可以根据实际情况决定是否CLOSE。