RFR: 8156484: ZipFile retains too much native memory from caching Inflaters

Martin Buchholz martinrb at google.com
Thu May 19 19:56:40 UTC 2016


Peter and Sherman,

I'm still quixotic fighting java memory bloat.  Caching Inflaters at
all is only barely profitable; a one-element Inflater cache is
probably fine for those apps that occasionally iterate through the
classpath.  I don't want ThreadLocal bloat; I want _all_ the Inflaters
to go away by themselves after a while e.g. in a long-running server.
I'm open to having the cache contain more than one element, as long as
they go away eventually.  If so, I would choose a design based on
linked nodes, still with a WeakReference to make them go away.

On Thu, May 19, 2016 at 9:49 AM, Peter Levart <peter.levart at gmail.com> wrote:
>
>
> On 05/19/2016 06:31 PM, Xueming Shen wrote:
>
>
> Martin,
>
> Given we now only cache one deflater per Zip/JarFile object, is
> WeakReference here really
> necessary? Basically wr is based on the vm heap memory and deflater is a
> native memory,
> arguably we are using the wrong measurement to decide whether or not to give
> up the
> deflater's native memory. Given someone (classloader) is keeping hundreds
> and thousands
> of jar/zip files alive, is it reasonable to assume it'd better to keep the
> 32k cache for each
> of them?
>
>
> It would perhaps make more sense to keep a 32k native object for each thread
> - not each jar file, don't you think?
>
> Regards, Peter
>
>
>
> -Sherman
>
> On 5/19/16 8:00 AM, Martin Buchholz wrote:
>
> On Thu, May 19, 2016 at 7:29 AM, Peter Levart <peter.levart at gmail.com>
> wrote:
>
> But I have reservation for the implementation of one-element global cache of
> Inflater. This cache can't be efficient. In order for cache to be efficient,
> majority of calls to ZipFile.getInputStream(zipEntry) would have to be
> accompanied by a corresponding explicit close() for the input stream before
> the WeakReference to the cached Inflater is cleared.
>
> That's my assumption.  In most cases, failure to close something that
> can be closed is a bug.
> If there's code in the JDK that fails to do that, it should be fixed
> independently.
>
> The "assert !inf.ended()" in
> releaseInflater() can therefore fail as final() methods on individual
> objects that are eligible for finalization may be invoked in arbitrary
> order.
>
> Yeah, that's a bug. We can only assert after we verify that the
> Inflater is still weakly reachable.
> Updating my webrev with:
>
>        * Releases the Inflater for possible later reuse.
>        */
>       private static void releaseInflater(Inflater inf) {
> -        assert !inf.ended();
>           CachedInflater cachedInflater = inflaterCache.get();
>           if (inf != cachedInflater.get()) {
>               inf.end();
>           } else {
>               // "return" the Inflater to the "pool".
> +            assert !inf.ended();
>               inf.reset();
>               assert cachedInflater.inUse.get();
>               cachedInflater.inUse.set(false);
>
>
>
>



More information about the core-libs-dev mailing list