包装多个输出流对象时的 Java 输出流行为

标签 java memory-leaks garbage-collection object 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”变量。我想知道这是否会导致内存泄漏?创建的旧“os”对象实际上会发生什么?换句话说,有 4 个使用“new”创建的对象,但被重新分配给相同的“os”变量。我发现很难理解,因为新对象的创建/功能本身在内部依赖于旧对象。

最佳答案

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

一个例子是这样的:

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 或重新分配它,然后即可回收内存。

在包装的情况下,一旦“根”对象消失,并且只要没有其他 Activity 引用,所有包装对象都将有资格进行垃圾回收。因此,一旦启动方法返回,其中创建的所有对象就应该能够被收集。

关于包装多个输出流对象时的 Java 输出流行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1845737/

相关文章:

java - JPanel 上的 mouseListener 问题

java - 使用 CrudRepository.save(Entity) 使用 spring-data-jdbc 插入具有预定义 @ID 字段的实体

delphi - 如何正确处理字符串数组以防止内存泄漏?

使用 client-auth 的 Java 客户端在代码中工作,但不使用 vm-arguments

java - 使用 "JSP Document"/"JSP in XML notation"是否意味着输出 XHTML?

c# - .NET 内存加载约 40 张图像时出现问题,内存未回收,可能是由于 LOH 碎片

ios - 奇怪和陌生的内存行为

允许死内存的Java垃圾收集?

java - 为什么下面的代码中finalize没有给出空指针异常?

go - 为什么 "concurrent"Go GC 阶段看起来是停止世界的?