Što uzrokuje java.lang.OutOfMemoryError: nije moguće stvoriti novu izvornu nit

1. Uvod

U ovom uputstvu razgovarat ćemo o uzroku i mogućim lijekovima za java.lang.OutOfMemoryError: nije moguće stvoriti novu izvornu nit pogreška.

2. Razumijevanje problema

2.1. Uzrok problema

Većina Java aplikacija je višenitne prirode, koji se sastoji od više komponenata, izvodi određene zadatke i izvodi se u različitim nitima. Međutim, temeljni operativni sustav (OS) nameće ograničenje maksimalnom broju niti koje Java aplikacija može stvoriti.

JVM baca nije u mogućnosti stvoriti novu izvornu nit pogreška kada se JVM traži osnovni OS za novu nit, a OS nije u stanju stvoriti nove niti jezgre također poznate kao OS ili sistemske niti. Slijed događaja je sljedeći:

  1. Aplikacija koja se izvodi unutar Java Virtual Machine (JVM) traži novu nit
  2. Izvorni kôd JVM šalje zahtjev OS-u za stvaranje nove niti jezgre
  3. OS pokušava stvoriti novu nit jezgre koja zahtijeva dodjelu memorije
  4. OS odbija dodjelu matične memorije jer bilo što
    • Podnositelj zahtjeva Java proces je iscrpio svoj adresni prostor memorije
    • OS je ispraznio virtualnu memoriju
  5. Tada Java proces vraća java.lang.OutOfMemoryError: nije moguće stvoriti novu izvornu nit pogreška

2.2. Model raspodjele niti

OS obično ima dvije vrste niti - korisničke niti (niti koje je kreirala Java aplikacija) i niti jezgre. Korisničke niti podržane su iznad niti jezgre, a OS-om upravlja niti jezgre.

Između njih postoje tri zajednička odnosa:

  1. Mnogo-prema-jednom - Mnogo korisničkih niti preslikavaju se u jednu nit jezgre
  2. Jedan na jedan - Mapa jedne korisničke niti na jednu nit jezgre
  3. Mnogo-mnogima - Mnogo korisničkih niti multipleksiraju se na manji ili jednak broj niti jezgre

3. Ponavljanje pogreške

Ovaj problem možemo lako stvoriti stvaranjem niti u neprekidnoj petlji i zatim natjerati niti da čekaju:

while (true) {new Thread (() -> {try {TimeUnit.HOURS.sleep (1);} catch (InterruptedException e) {e.printStackTrace ();}}). start (); }

Budući da se držimo svake niti sat vremena, dok kontinuirano stvaramo nove, brzo ćemo doći do maksimalnog broja niti s OS-a.

4. Rješenja

Jedan od načina za rješavanje ove pogreške je povećanje konfiguracije ograničenja niti na razini OS-a.

Međutim, ovo nije idealno rješenje jer OutOfMemoryError vjerojatno ukazuje na programsku pogrešku. Pogledajmo neke druge načine za rješavanje ovog problema.

4.1. Korištenje okvira usluge izvršitelja

Iskorištavanje Javinog izvršnog okvira za administraciju niti može riješiti ovaj problem u određenoj mjeri. Zadani okvir izvršne službe ili prilagođena konfiguracija izvršitelja može kontrolirati stvaranje niti.

Možemo koristiti Izvršitelji # newFixedThreadPool metoda za postavljanje maksimalnog broja niti koje se mogu istodobno koristiti:

ExecutorService executorService = Izvršitelji.newFixedThreadPool (5); Izvodljivo runnableTask = () -> {try {TimeUnit.HOURS.sleep (1); } catch (InterruptedException e) {// Obrada iznimke}}; IntStream.rangeClosed (1, 10) .forEach (i -> executorService.submit (runnableTask)); assertThat ((((ThreadPoolExecutor) executorService) .getQueue (). size (), je (jednakTo (5)));

U gornjem primjeru prvo kreiramo spremište s fiksnom niti s pet niti i izvršivim zadatkom zbog kojeg niti čekaju jedan sat. Zatim deset takvih zadataka podnosimo spremištu niti i tvrdimo da pet zadataka čeka u redu izvršnih usluga.

Budući da spremište niti ima pet niti, u svakom trenutku može obraditi najviše pet zadataka.

4.2. Snimanje i analiza odlagališta niti

Snimanje i analiza izvatka niti korisno je za razumijevanje statusa niti.

Pogledajmo primjer odlagališta niti i saznajmo što možemo naučiti:

Gornja snimka niti je iz Java VisualVM-a za prethodno predstavljeni primjer. Ova snimka jasno pokazuje kontinuirano stvaranje niti.

Jednom kada utvrdimo da postoji kontinuirano stvaranje niti, možemo snimiti dump niti aplikacije kako bismo identificirali izvorni kod koji stvara niti:

U gornjoj snimci možemo identificirati kod odgovoran za stvaranje niti. To pruža koristan uvid za poduzimanje odgovarajućih mjera.

5. Zaključak

U ovom smo članku saznali više o java.lang.OutOfMemoryError: nije moguće stvoriti novu izvornu nit pogrešku, i to smo vidjeli to je uzrokovano pretjeranim stvaranjem niti u Java aplikaciji.

Istražili smo neka rješenja za rješavanje i analizu pogreške promatrajući ExecutorService analiza okvira i analiza odlagališta niti kao dvije korisne mjere za rješavanje ovog problema.

Kao i uvijek, izvorni kôd članka dostupan je na GitHubu.