为什么 Java 的 InflaterInputStream(和其他类似类)

在 Java 8 中,close()方法InflaterInputStream如下所示


public void close() throws IOException {

    if (!closed) {

        if (usesDefaultInflater)

            inf.end();

        in.close();

        closed = true;

    }

}

usesDefaultInflater是一个布尔值,仅true当使用下面的构造函数时


public InflaterInputStream(InputStream in) {

    this(in, new Inflater());

    usesDefaultInflater = true;

}

任何其他构造函数(例如下面的构造函数)都会导致此布尔值设置为 false


new InflaterInputStream(decryptInputStream, new Inflater(), 4096);

因此,除非您使用默认构造end()函数,否则不会在 上调用该方法,这意味着在 Finalizer 线程可能在关闭后很长时间内调用Inflater该方法之前会消耗不必要的本机内存。请参阅下面的实现。finalizeInflaterInflaterInputStreamInflater


/**

 * Closes the decompressor and discards any unprocessed input.

 * This method should be called when the decompressor is no longer

 * being used, but will also be called automatically by the finalize()

 * method. Once this method is called, the behavior of the Inflater

 * object is undefined.

 */

public void end() {

    synchronized (zsRef) {

        long addr = zsRef.address();

        zsRef.clear();

        if (addr != 0) {

            end(addr);

            buf = null;

        }

    }

}


/**

 * Closes the decompressor when garbage is collected.

 */

protected void finalize() {

    end();

}

为了解决这个问题,你需要像这样重写close方法InflaterInputStream


new InflaterInputStream(decryptInputStream, new Inflater(), 4096) {    

    @Override

    public void close() throws IOException {

        try {

            super.close();

        } finally {

            inf.end();

        }

    }

}

end()这很容易被忽略,在我看来,默认调用并允许用户通过提供一个您可以指定的构造函数来覆盖该行为可能是明智的false,或者至少是一个使用默认值Inflater但也允许您设置缓冲区大小。


无论如何,我猜它的设计方式有一些合乎逻辑的原因,而我只是没能理解它。希望有人能赐教。。。


这也适用于DeflaterInputStream、DeflaterOutputStream等InflaterOutputStream。


狐的传说
浏览 150回答 2
2回答

牧羊人nacy

Java Runtime Library 中有许多方法采用例如 an OutputStream(例如Files.copy())。除非这些方法明确声明该方法将关闭流,否则不会关闭流。关闭流是流“所有者”的责任,例如方法的调用者。类似地,InflaterInputStreamthat的构造函数都不会Inflater声明它们将end()执行Inflater,这意味着它们不会执行。在需要时由调用者来结束它。Inflater当使用为您创建的构造函数时, 成为该内部InflaterInputStream的“所有者” ,因此结束. InflaterInflaterInputStreamInflater资源管理资源管理的一般准则是,除非另有说明,分配资源的人负责释放(关闭、结束……)资源。Inflater是一种资源,因此应用正常的资源管理规则。

弑天下

与许多“为什么”问题一样,这是一个有根据的猜测。我没有看到任何明确的解释,所以谁知道原来的程序员在想什么?无论如何,请对我的回答持保留态度。其他构造函数都采用实例Inflater,这意味着用户具有对 (internal) 的引用Inflater。请注意,这些类没有吸气剂Inflater。因此,用户引用它的唯一方法是从外部传递它(好吧,那并使用反射,但我们不要去那里)。所以也许假设是因为用户通过了他自己的Inflater实例,然后他想管理自己Inflater,可能会在这个蒸汽结束后重新使用它。因此,Inflater在流关闭时关闭不是一个好主意。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java