Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
包装多个Outputstream对象时的Java Outputstream行为_Java_Memory Leaks_Garbage Collection_Object_Outputstream - Fatal编程技术网

包装多个Outputstream对象时的Java Outputstream行为

包装多个Outputstream对象时的Java Outputstream行为,java,memory-leaks,garbage-collection,object,outputstream,Java,Memory Leaks,Garbage Collection,Object,Outputstream,我有一个对文件Outputstream进行压缩、加密和校验的代码。下面是代码- private void start() { OutputStream os = null; try { os = new FileOutputStream("/some/file"); os = wrapAllRequiredTransforms(os); //Write to os } finally { os.close(

我有一个对文件Outputstream进行压缩、加密和校验的代码。下面是代码-

private void start() {
    OutputStream os = null;
    try {
        os = new FileOutputStream("/some/file");
        os = wrapAllRequiredTransforms(os);

        //Write to os
    } finally {
        os.close();
    }
}

private wrapAllRequiredTransforms(OutputStream os) {
    if(checkSumRequired) {
        os = wrapOStreamWithCheckSum(os);
    }

    if(encryptionRequired) {
        os = wrapOStreamWithCipher(os);
    }

    if(compressRequired) {
        os = wrapOStreamWithCompress(os);
    }
}

private OutputStream wrapOStreamWithCheckSum(OutputStream os) throws Exception {
    os = new DigestOutputStream(os, MessageDigest.getInstance("MD5"));
    return os;
}

private OutputStream wrapOStreamWithCipher(OutputStream os) throws Exception {
    SecretKeySpec secretKeySpec = new SecretKeySpec(//SomeKey, encryptionAlgorithm);
    Cipher cipher = Cipher.getInstance(encryptionAlgorithm); 
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
    return new CipherOutputStream(os, cipher);
}

private OutputStream wrapOStreamWithCompress(OutputStream os) throws Exception {
    return new GZIPOutputStream(os);
}

正如您在这里看到的,我正在包装用于加密、压缩等的os对象,然后在每个wrapOStreamWithCheckSum、wrapOStreamWithCipher和wrapOStreamWithCompress方法中使用new创建的不同对象重新分配os变量。我想知道这是否会导致内存泄漏?创建的旧操作系统对象实际会发生什么情况?换言之,有4个对象使用new创建,但被重新分配给同一os变量。我发现很难理解,因为新的对象创建/运行本身是依赖于旧对象内部的。

< P> java有一个自动垃圾收集机制,所以你不必担心不释放那些会在C++中产生内存泄漏的旧对象。基本上,您只需确保没有对不再指向使用变量os的对象的悬空引用。

这是Java中的标准做法,而且是安全的

发生的情况是,每个新对象在内部保留对传入对象的引用。此过程称为包装或委派。当您关闭最后一个操作系统时,它会将方法调用传递给包装的实例


这样,一次调用将关闭所有对象,释放最外层的操作系统将释放所有对象。

只有当对象可通过堆栈引用且不再希望它位于内存中时,才会出现内存泄漏

例如:

public class Main
{
    private static CommandLineArgumentParser parser;

    public static void main(final String[] argv)
    {
        parser = new CommandLineArgumentParser(argv);
        ... use the parser
        ... never use the parser again ....
        ... do a bunch of work ...
    }
}
解析器不再被使用,但仍然可以访问,因此从技术上讲,它是一个内存泄漏内存,您不想再使用它,但垃圾收集器还不能回收它

为了使它不再被使用,您需要做的就是将其设置为null或重新分配,然后可以收集内存


在包装的情况下,一旦根对象消失,并且只要没有其他活动引用,所有包装对象都可以进行垃圾收集。因此,一旦start meoth返回在中创建的所有对象,就应该能够收集这些对象。

对outputstreams的所有引用都只是局部变量。因此,在start终止后,将不再有对流的引用,并且“大GC”将被清除


如果您确实想要确定,并且手头有一个实际的eclipse SDK和实际的Java 6+,那么您可以在os.close行中添加一个断点,并检查是否有一些意外的对象包含对您的流的引用。

您的try/finally失败了。如果(比如)找不到文件会发生什么。使用获取;尝试{use;}最后{release;}。在这种情况下,类似于:final OutputStream rawOut=new FileOutputStream/some/file/;试试{final OutputStream out=wraprawOut;…}最后{rawOut.close;}。谢谢汤姆!是的,您是对的,这里没有处理错误条件,事实上,上面的代码片段在复制到程序时甚至不会编译。以上代码片段仅试图说明我试图理解的问题: