Skip to content
This repository was archived by the owner on Aug 13, 2026. It is now read-only.
This repository was archived by the owner on Aug 13, 2026. It is now read-only.

Webapp classloader leaks problem with RiakNode.Builder or RiakClient [JIRA: CLIENTS-962] #660

Description

@monday0rsunday

I'm using Riak java client (2.0.4) for our jax-rs services and I've encountered permgen OOM leak when reloading services.

I've created an example, just using this Listener (and uncomment cluster/client code) for any webapps, and seeing permgen space increase when reloading services (at least 2 times).

public class ContextListener implements ServletContextListener {
    public static RiakCluster cluster = null;
    public static RiakClient client = null;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        try {
            // RiakNode.Builder have perm gen leak when initialize any instance
            RiakNode.Builder builder = null;
            // builder = new RiakNode.Builder();

            List<String> addresses = new LinkedList<String>();
            addresses.addAll(Arrays.asList("anyip:port".split(",")));
            // or memleak when call buildNodes also
            List<RiakNode> nodes = null;
            // nodes = RiakNode.Builder.buildNodes(builder, addresses);
            // cluster = new RiakCluster.Builder(nodes).build();
            // cluster.start();

            // client = RiakClient.newClient();
        } catch (Exception e) {

        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        if (cluster != null)
            cluster.shutdown();
        if (client !=null)
            client.shutdown();
    }

}

Thanks,
Cong Nguyen

Activity

  1. changed the title [-]Webapp classloader leaks problem with RiakNode.Builder or RiakClient[/-] [+]Webapp classloader leaks problem with RiakNode.Builder or RiakClient [JIRA: CLIENTS-962][/+] on Aug 14, 2016
  2. alexmoore commented on Aug 19, 2016

    @alexmoore
    Contributor

    Hi Cong,

    What happens if you run await() on the Future<Boolean> that cluster.shutdown() and client.shutdown() return?

  3. alexmoore commented on Aug 19, 2016

    @alexmoore
    Contributor

    @monday0rsunday Also, do you have a minimum reproducing java project you could share to help speed up bug hunting?

  4. monday0rsunday commented on Aug 21, 2016

    @monday0rsunday
    Author
  5. alexmoore commented on Sep 14, 2016

    @alexmoore
    Contributor

    So after running the refresh a few times, I see some extra WebAppClassLoaders sitting on the Heap:

    workspace_-java_ee-_users_alex_src_other_riak_perm_build_distribution_heap2_bin-_eclipse

    If we dig down and "Merge Shortest Paths to GC Roots", it shows something on the Jetty Scanner TimerThread, but no big red flags.
    workspace_-java_ee-_users_alex_src_other_riak_perm_build_distribution_heap2_bin-_eclipse

    Do you know if you can reproduce this with a console app, or another webapp container?

  6. alexmoore commented on Sep 19, 2016

    @alexmoore
    Contributor

    @monday0rsunday What version of Java are you running?

  7. alexmoore commented on Sep 20, 2016

    @alexmoore
    Contributor

    @monday0rsunday Aha! I think I found our culprit. It looks like the object that gets stuck in memory is one io.netty.util.internal.IternalThreadLocalMap object, which is ThreadLocal. It looks like this is a known issue that the Netty team has no control over. I'll see if there's a workaround...

  8. monday0rsunday commented on Sep 20, 2016

    @monday0rsunday
    Author

    @alexmoore I'm not sure about version exactly, but there are two major versions I tested: 7 and 8.

  9. alexmoore commented on Sep 20, 2016

    @alexmoore
    Contributor

    @monday0rsunday One workaround is to add the following to your contextDestroyed(..) method after you call client.shutdown.get();:

    io.netty.util.concurrent.FastThreadLocal.removeAll();
    io.netty.util.concurrent.FastThreadLocal.destroy();

    This seems to allow the most PermGen/Metaspace space to be GC'd (Java 7 running here):

    centos_7

    I'll need to do some more investigation to see if there's any more permanent fixes/workarounds for this Netty ThreadLocal issue, or if there's anything else not getting collected.

  10. monday0rsunday commented on Sep 20, 2016

    @monday0rsunday
    Author

    @alexmoore Thank you, I'll try it and feed back to you.

  11. alexmoore commented on Sep 20, 2016

    @alexmoore
    Contributor

    @monday0rsunday So looking into it more today, if we:

    1. Add those two lines to cleanup netty
    2. Start server
    3. Take Heap Dump Import trifork's PBC Client, Map/Reduce filter support #1
    4. Touch the xml file to force a redeploy
    5. Force GC via VisualVM
    6. Take Heap Dump add file extension so the README renders nicely on GitHub #2
    7. Compare the dumps

    After the refresh + GC, there are no additional instances of any io.netty or com.basho.riak classes in dump 2, which means that everything in those two libs are getting GC'd over the refresh.

    There are some new additional objects in dump 2 that I can't find homes for, but I think they are related to the Jetty reload:

    cursor_and_centos_7

    centos_7

    Digging further into the big java.lang.ref.Finalizer difference, this seems related to the Jar file reloading, same with the byte[], String, etc differences. Those objects seem to get GC'd later on after everything is reloaded or finalized.

    centos_7

    Please try adding those two lines to your web service contextDestroyed(...) method and let me know if you see any more errant behavior.

  12. monday0rsunday commented on Sep 20, 2016

    @monday0rsunday
    Author

    @alexmoore yes, after adding two lines of code, I haven't seen any leaked WebAppClassLoader. Although there're some other leaked classes, but they won't be more serious than WebAppClassLoader, so the problem can be considered to be solved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions