OutOfMemoryError: GC Overhead Limit depășit

1. Prezentare generală

Mai simplu spus, JVM se ocupă de eliberarea memoriei atunci când obiectele nu mai sunt folosite; acest proces se numește Garbage Collection (GC).

GC Overhead Limita a fost depășită eroarea este una din familia java.lang.OutOfMemoryError și este o indicație a unei resurse (memorie) epuizare.

În acest articol rapid, vom analiza ce cauzează eroarea java.lang.OutOfMemoryError: GC Overhead Limit Exceeded și cum poate fi rezolvată.

2. Eroare depășită limită de cheltuieli generale GC

OutOfMemoryError este o subclasă a java.lang.VirtualMachineError ; este aruncat de JVM atunci când întâmpină o problemă legată de utilizarea resurselor. Mai precis, eroarea apare atunci când JVM a petrecut prea mult timp executând Garbage Collection și a reușit să recupereze doar foarte puțin spațiu.

Conform documentelor Java, în mod implicit, JVM este configurat pentru a arunca această eroare dacă procesul Java își petrece mai mult de 98% din timpul său făcând GC și când doar mai puțin de 2% din heap este recuperat în fiecare rulare. Cu alte cuvinte, acest lucru înseamnă că aplicația noastră a epuizat aproape toată memoria disponibilă, iar Garbage Collector a petrecut prea mult timp încercând să o curățe și a eșuat în mod repetat.

În această situație, utilizatorii se confruntă cu o lentitudine extremă a aplicației. Anumite operații, care de obicei se finalizează în milisecunde, necesită mai mult timp pentru a finaliza. Acest lucru se datorează faptului că CPU își folosește întreaga capacitate pentru colectarea deșeurilor și, prin urmare, nu poate îndeplini alte sarcini.

3. Eroare în acțiune

Să vedem o bucată de cod care aruncă java.lang.OutOfMemoryError: GC Overhead Limit Exceded.

Putem realiza acest lucru, de exemplu, adăugând perechi cheie-valoare într-o buclă neterminată:

public class OutOfMemoryGCLimitExceed { public static void addRandomDataToMap() { Map dataMap = new HashMap(); Random r = new Random(); while (true) { dataMap.put(r.nextInt(), String.valueOf(r.nextInt())); } } }

Când se invocă această metodă, cu argumentele JVM ca -Xmx100m -XX: + UseParallelGC ( dimensiunea heap Java este setată la 100MB și algoritmul GC este ParallelGC), obținem o eroare java.lang.OutOfMemoryError: GC Overhead Limit Exceeded . Pentru a înțelege mai bine diferitele algoritmi de colectare a gunoiului, putem verifica tutorialul Oracle Java Garbage Collection Basics.

Vom primi java.lang.OutOfMemoryError: GC Overhead Limit Exceded error foarte rapid executând următoarea comandă din rădăcina proiectului:

mvn exec:exec

De asemenea, trebuie remarcat faptul că, în unele situații, s-ar putea să întâlnim o eroare de spațiu înainte de a întâmpina eroarea GC Overhead Limit Exceeded .

4. Soluționarea GC Overhead Limit Exceded Error

Soluția ideală este de a găsi problema de bază a aplicației, examinând codul pentru eventualele scurgeri de memorie.

Următoarele întrebări trebuie abordate:

  • Care sunt obiectele din aplicație care ocupă porțiuni mari din grămadă?
  • În ce părți ale codului sursă sunt alocate aceste obiecte?

De asemenea, putem folosi instrumente grafice automatizate, cum ar fi JConsole, care ajută la detectarea problemelor de performanță în cod, inclusiv java.lang.OutOfMemoryErrors.

Ultima soluție ar fi creșterea dimensiunii heap-ului prin modificarea configurației de lansare JVM. De exemplu, aceasta oferă 1 GB spațiu heap pentru aplicația Java:

java -Xmx1024m com.xyz.TheClassName

Cu toate acestea, acest lucru nu va rezolva problema dacă există scurgeri de memorie în codul real al aplicației. În schimb, vom amâna doar eroarea. Prin urmare, este mai recomandabil să reevaluați cu atenție utilizarea memoriei aplicației.

5. Concluzie

În acest tutorial, am examinat java.lang.OutOfMemoryError: GC Overhead Limit Exceeded și motivele din spatele acesteia.

Ca întotdeauna, codul sursă legat de acest articol poate fi găsit pe GitHub.