memory-leaksjava-11heap-dumpopenjdk-11java-memory-leaks

Why is Java11 keeping java.util.zip.ZipFile$Source on heap?


Can somebody help me understand if what I see is deliberate, correct behaviour or some kind of leak in Java11? Let's take a stupid-simple hello world app:

package com.example;

public class HelloWorld {
    public static void main(String[] args) throws InterruptedException {
        for( int i =0 ; i < 50; i++){
            Thread.sleep(1000);
            System.out.println("hello " + i);
        }
    }
}

The only interesting part is a jar dependency. It can be any jar, but to make the problem more spectacular let's use a big one - old gwt-user jar, which weigh 30MB:

plugins {
    id 'java'
}

group 'com.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    // https://mvnrepository.com/artifact/com.google.gwt/gwt-user
    compile group: 'com.google.gwt', name: 'gwt-user', version: '2.7.0'
}

Run the app, open the jvisualvm, make a dump and look for retained set of java.util.zip.ZipFile$Source:

jvisualvm heapdump

That jar from classpath (never used, actually) occupies 1.5MB of heap. It doesn't go away during GC, it doesn't go away when you are short of memory, I even saw these entries in OutOfMemory heapdumps.

The entry is obviously kept by a map java.util.zip.ZipFile$Source.files. From the source I can tell that this theoretically should be cleaned by a Common-Cleaner thread from InnocuousThreadGroup, but I don't see it happening.

I encountered this problem when migrating a small, lightweight Java app from JDK8 to JDK11. With low Xmx settings those jars use up significant portion of my heap as compared to JDK8.

So is it a bug or a feature?


Solution

  • This is deliberate.

    The observation that memory use seem to increase is caused by moving from a native to pure java-based implementation[1] for zip/jar files in JDK 9. Mainly for stability purposes.

    I'll note that the native implementation allocates similar and similarly sized data structures, but they were hidden out of sight from tools inspecting the java heap.

    But even though total memory footprint should be more or less neutral, there might be a need to increase the java heap size to encompass the increased java heap usage.

    [1] https://bugs.openjdk.java.net/browse/JDK-8145260