简体   繁体   中英

java server with jetty memory leak issue

I´m running this application with a Jetty server embedded. The application is slowly consuming more memory dispite the fact that the heap size does not change at all.

this is the command to start the application :

java -server -Xms1G -Xmx1G -Dfile.encoding=UTF-8

This is the chart from new relic with the RAM usage increase 在此输入图像描述 it started using 1140MB and after 8 hours finished with 1290MB

This is the jvisualvm chart of the heap. 在此输入图像描述

Any suggestions ?

[EDIT1] add dump https://www.dropbox.com/s/1gt1i9dhjtjauf0/gameserver-20160226-2107.zip?dl=0

[EDIT2] Here are some notes from my current investigation

= How Monitor memory outside the heap add parameters

-XX:NativeMemoryTracking=detail -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics

run command jcmd 3322 VM.native_memory summary @see https://devcenter.heroku.com/articles/java-memory-issues

= Checking the default thread stack size java -XX:+PrintFlagsFinal -version | grep ThreadStackSize

intx ThreadStackSize = 1024
How to reclaim the memory used by a Java thread stack?

= Understand the max memory Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss] @see https://plumbr.eu/blog/memory-leaks/why-does-my-java-process-consume-more-memory-than-xmx

= Actions Reduce the size of the thread stacks. (In theory, you can go as low as 64K ...)

-XX:ThreadStackSize=256

Reduce the Minimum percentage of heap free after GC to avoid expansion.

-XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=10

Now will continue monitoring ...

After lots of different types of investigations, I came back to the Eclipse Memory analyzer and tried once more ...

But this time I decided to trust the leak report that was saying :

One instance of "org.hibernate.internal.SessionFactoryImpl" loaded by "sun.misc.Launcher$AppClassLoader @ 0xc001d4f8" occupies 2.956.808 (21,05%) bytes. The memory is accumulated in one instance of "org.hibernate.internal.SessionFactoryImpl" loaded by "sun.misc.Launcher$AppClassLoader @ 0xc001d4f8".

Then I shift my investigation the my DAO implementation, expecting that I forgot to close one or other EntityManager call. That wasn´t the case, all of then were with a nice close() method call after use.

Then I realize that the problem could be on hibernate itself as the problematic object were a SessionFactory Impl, so I changed my DAO implementation to clear Hibernate first level cache every time I create an Entity Manager, as I wasn´t able to find a way to disable it.

End of the day result = IT WORKED !! :) the memory changes a litle and come back after some minutes, but don´t grow in a crazy way anymore (1000MB in 24hours).

Here is the code I changed, hope it helps someone.

public EntityManager getEntityManager(){
    if( emf == null ){
        if (parameters == null) {
            emf = Persistence.createEntityManagerFactory(persistenceUnitName);
        } else {
            emf = Persistence.createEntityManagerFactory(persistenceUnitName, parameters);
        }
    } else {
        emf.getCache().evictAll();
    }

    EntityManager em = emf.createEntityManager();
    return em;
}

The key is here : emf.getCache().evictAll();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM