Java - Mi eszi a memóriát?

Fórumok

Van egy szerverem. Java 11-re nemrég tértünk át, és az egyik szerver megbokrosodott.

Eddig beérte max. 5-6G memóriával, most hirtelenjében annyit eszik amennyit csak tud.

Ha készítek belőle memory dumpot, pl. egy 23G-ás RES memória foglalásról, akkor a profiler azt mondja, hogy az élő objektumok mérete 1G alatti. Mi a fene lehet a másik 22G?

Ötletek?

UPDATE:
A heap memórián az élő objektumok 900 mega körül vannak. Ezen kívül van még 22 (most már ~30) giga valami még.
Azaz mivel lehetne kideríteni, hogy mi az ami a heap-on kívül eszi a memóriát? 

Hozzászólások

nem értek a JVM-hez de linux szintjén milyen memóriáról van szó? file cache, anon page?

Linux szinten használt memóriáról van szó azaz resource memória, azaz a topban pl. itt látod: RES.

hotspot vagy j9? a jvm-váltáson túl a kódhoz is hozzányúltatok? a dependenciák változtak?

Köszönöm, de ez elég hosszadalmas lenne. Hiszen át kellene nézni a WildFly változásokat, a dependency változásokat (melyik lehet hibás?), kódban is rengeteg volt, meg még a Java-nak is lehet gondja.

Nem a heap ami önmagában eszik, hanem valami a heapen kívül növekszik. Ha azt lehetne valahogy megállapítani, hogy mi a heap-en kívül a tartalma a memóriának, az sokat segíthetne.

Mekkora heap-et adtál amúgy a JVM-nek? Ha azon bőven túlterjeszkedik, akkor a JVM a probléma általában (és/vagy Unsafe interfészen át való off-heap memóriafoglalás), azt hiába nézed Java profiler-el, nem fogod látni a hibát.

Próbálj ezzel indítani: `-XX:NativeMemoryTracking=[summary | detail]`

Köszönöm az eddigi segítségeteket.

2 további tapasztalat:

1. Ami viszont előjött, ha be van kapcsolva ez a -XX:NativeMemoryTracking akkor jobban eszi a memóriát. Így mos éppen az ellen-teszt megy. Azaz ennek a bekapcsolása nélkül igyekszem növelni a memórahasználatot. Egyelőre nem sikerült. :-(

2. Közben megnéztem az Eclipse mat-al és a YourKit-el is a memory dumpot. Az Mat-al az jött ki, hogy van 900m live object és van ~4.1G kitakarítandó objektum a heap-en.

- Ha csak a live memóriát nézem: 11 instances of "org.hibernate.internal.SessionFactoryImpl", loaded by "org.jboss.modules.ModuleClassLoader @ 0x7ef572f327d0" occupy 0,24 GB (27,56%) bytes.
- Ha a teljes heap-ot nézem, akkor a (azokat is figyelembe veszem, amiket a GC még nem takarított ki): 3 380 968 instances of "org.jboss.as.security.plugins.ModuleClassLoaderLocator$CombinedClassLoader", loaded by "org.jboss.modules.ModuleClassLoader @ 0x7ef571ea34c8" occupy 4,21 GB (56,06%) bytes.

Ez is elég furcsa viselkedés. Vagy nem G1-nél? Itt már nem tudom mekkora xmx volt megadva.

Esetleg érdemes lenne egy memória analizálást is csinálni, hátha a kódban is változott valami, vagy előjött egy olyan eset, amivel eddig nem foglalkoztatok.

Ha van heap dump (esetleg több is, az még jobb) akkor ezzel az ingyenes tool-lal meg tudjátok nézni, hogy mi is a helyzet:

 

https://www.eclipse.org/mat/

hmap kilistázza milyen class-ból hány db van a memóriában és mennyit foglal

Eszi is a memóriát vagy csak úgy gondolod, hogy eszi? Van ebből a fajta szerverből még és azok nem csinálják, vagy egyedi szerver és/vagy egyedi konfigurációval?

Köszönöm.

Eszi. Amikor kezdte elérni a fizikai memória határát, egyre lassabb is lett. Annyira lassú, hogy kénytelenek voltunk újraindítani.

Van több szerverünk is. De ebből 2-ő van, mindkettő ugyanazt produkálja.
A többi más alkalmazásainkkal futó szerveren is látunk hasonlót, de ott jóval lassabban eszi a memóriát. Napi 300-400-600 mega fogy a többi szerveren. De még bőven kereten belül vannak.
Ez meg 1 nap alatt feleszik 20G-át. 

Az jo, akkor legalabb reprodukalhato.

java.nio kornyeken nezz korul, abban vannak bufferek, amik off-heap memoryt foglalnak. Valszleg valahol nem lesznek lezarva (vagy application code vagy wildfly code).

https://dzone.com/articles/troubleshooting-problems-with-native-off-hea…

https://dzone.com/articles/understanding-java-buffer-pool

Amugy lepjel vissza 1-2 wildfly verziot, ha lehetseges, hatha segit. Meg ugy altalaban is ajanlatos semmit nem hasznalni a wildfly-bol, ami nem public api module. Inkabb csomagold be a deploymentedbe a neked kello libet, es akkor nem fogsz szivni uj wildfly eseten.

a /proc alatt a megfelelő PID-nèl mi látható? érdemes lenne megmutatni a jól működőt is.

maps, numa_maps, smaps (vagy smaps_rollup), status -> lehet, hogy ezekkel egy lépéssel sem kerülsz közelebb. talán segítenek, talán nem. mondanám, hogy próbálj egy strace-t az érintett PID-re, de ugyanaz a gond, vagy fog segíteni, vagy nem (de inkább nem). coredumpod van?

Köszönöm. Egyedül a status fájlhoz volt jogom:

Ebből ami érdekes lehet:

VmLck:         0 kB
VmPin:         0 kB
VmHWM:  11907748 kB
VmRSS:  11897448 kB
RssAnon:        11873172 kB
RssFile:           24276 kB
RssShmem:              0 kB
VmData: 23113716 kB
VmStk:       132 kB
VmExe:         4 kB
VmLib:     26560 kB
VmPTE:     23872 kB
VmSwap:        0 kB
Threads:        171

Ez a folyamatosan novekvo memoria hasznalat a JVM heap-en kivul eleg erost memoryleak-re utal. Az nem lenne baj, ha megenne az osszes memoriat, hiszen ez a dolga, csak kozben tisztitani is kellen (amennyiben a linux virtual memory-ban az adott page-ek felszabadithatoak lennenek, de ezek szerint nem lesznek azok).

Nem nagyon vagom a java-t en sem, de nalunk akkor szoktak belassulni a java alkalmazasok amikor a GC tul hosszu ideig, tul sokat kell takaritson. Mondjuk akkor a cpu usage is az egekben szokott lenni. De ha jol tudom a GC csak a jvm heap-et takaritja nem? Mondom nem ertek hozza.

En pmap-al is megneznem periodikusan a process virtual memory hasznalatat, hogy lassam hol novekszik a mi. Aztan ott a /proc/PID/smaps idonkenti leszedese es diffe-lgetese. Aztan vannak az inygenes tool-ok mtrace es tarsai. Tuti van valami a java-ra is.

na talaltam valamit: 

https://dzone.com/articles/finding-java-memory-leaks-from-a-heap-dump

Egyáltalán milyen funkciója van az APP-nak?

nincs benne vhol jni ami elkezdett leak-lni?

+1

Ha A directmemory kimutatásokban nem szerepel, akkor JNI leakelhet. Az ilyet a legnehezebb megfogni, ha ez bárkit megnyugtat :-).

Ha Java DirectMemory leakel, akkor az a Heap Dumpban látható lehet: A DirectByteBuffer típusú objektumok szaporodnak. (Vagy valami nio osztály, ha esetleg azok is foglalnak ilyen memóriát.) Ezt meg lehet a Heap Dump alapján találni.

Ha a natívak leakelnek, azt már nehezebb megtalálni.

subscribe.

Talisker Single Malt Scotch Whisky aged 10 years - o.k. Yamazaki is playing as well :)

ha kidumpolod a 22 giga memót és nyomsz rá egy strings parancsot, lehet hogy ezerszer ismétlődni fog vmi nyom, akár jdbc driver, akár bármi más

Nem nagyon hiszem hogy a 16g heap valid igény lenne, érdemes lenne sokkal kisebbel próbálkozni.

Akkor hamarabb elkezd aktívkodni a gc, kisebbek, kezelhetőbbek a dumpok.

Ha non-heap probléma van annak az arányai is jobban látszanak, hamarabb tolódik arra a memória igény.

Egyelőre úgy tűnik JVM hibába futottunk. Egy új 11-es java telepítése ígéretesnek tűnik.

Köszi! Mi is utazunk Javában, és nem árt hallani ezekről. Jól értem, hogy az ilyen dinamikusan osztályokat generáló-betöltő-majd kidobó könyvtárakkal jön csak elő ez az issue?

Az is kiderült, hogy melyik könyvtár csinál ilyen nagytömegű osztálybetöltést, és mi célból?

Odassatok! :)

 

JEP 387: Elastic Metaspace

 

Return unused HotSpot class-metadata (i.e., metaspace) memory to the operating system more promptly, reduce metaspace footprint, and simplify the metaspace code in order to reduce maintenance costs.

 

http://openjdk.java.net/jeps/387