在更改System.out 引用之后,进行再次修改时,如果不把之前的OutputStream关闭掉,会不会造成资源的泄露? 从而引发内存问题?
比如 //①保留系统默认流对象
PrintStream out = System.out;
//②然后更改
System.out = new new PrintStream();
//③还原默认outputStream
System.out = out; 在执行第三步的时候,如果没有对步骤2中System.out流进行关闭操作,会不会产生问题? 有必要调用System.out.close()方法吗?
比如 //①保留系统默认流对象
PrintStream out = System.out;
//②然后更改
System.out = new new PrintStream();
//③还原默认outputStream
System.out = out; 在执行第三步的时候,如果没有对步骤2中System.out流进行关闭操作,会不会产生问题? 有必要调用System.out.close()方法吗?
如果写例子程序肯定不会有问题。
系统是涉及到大文件的操作。 用的是ant提供的一个DemuxOutputStream类,用的是ant-task
不好意思打错了是System.setOut(out);
lz写的是
PrintStream out = System.out;
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进程不停止,操作系统这一层一直会开启这个流而占用一定的资源。
一家之言,谨慎采纳。
user.xxxx
....
user = null;
没异常么?
另外 如果将System.out的输出流换成普通的输出流 比如输出到某个文件上 可以不可以呢?
输出到本地文件理论上可以,实际试验后发现真的可以。
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);
}
}
我查了好多地方了 自己也进行了测试, 结论还是无法确定。
不过有个奇怪的问题:
在同一jvm实例(进程)中只要有一个程序改变了System.out,其他程序中是否也被改变?目前我在eclipse中新建一个类,改变System.out,再用无限循环执行,其每次启动后修改前的hashcode都是一致的(eclipse和正在运行的一个java程序分占了两个javaw.exe进程。一个javaw.exe进程就是一个jvm实例?)
如果你使用System.setOut,使用了自己的输出流,如果这个流指向网络或者文件系统,那么就要close掉了。