Mi okozza a java.lang.OutOfMemoryError alkalmazást: nem lehet új natív szálat létrehozni

1. Bemutatkozás

Ebben az oktatóanyagban megvitatjuk a probléma okát és lehetséges orvoslását java.lang.OutOfMemoryError: nem lehet új natív szálat létrehozni hiba.

2. A probléma megértése

2.1. A probléma oka

A legtöbb Java alkalmazás többszálas jellegű, amely több összetevőből áll, meghatározott feladatokat hajt végre, és különböző szálakban hajtja végre. Azonban a mögöttes az operációs rendszer (OS) korlátot szab a szálak maximális számára amelyet egy Java alkalmazás létrehozhat.

A JVM dob egy nem tud új natív szálat létrehozni hiba, amikor a A JVM új szálat kér az alapul szolgáló operációs rendszertől, és az operációs rendszer nem képes új rendszermag-szálak létrehozására, más néven operációs rendszer vagy rendszerszálak. Az események sorrendje a következő:

  1. A Java virtuális gépen (JVM) belül futó alkalmazás új szálat kér
  2. A JVM natív kód kérést küld az operációs rendszer számára egy új kernl szál létrehozására
  3. Az operációs rendszer megkísérel egy új kernelszálat létrehozni, amely memóriafoglalást igényel
  4. Az operációs rendszer elutasítja a natív memória kiosztását, mert egyik sem
    • A kérő A Java folyamat kimerítette memória címterét
    • Az operációs rendszer kimerítette virtuális memóriáját
  5. A Java folyamat ezután visszaadja a java.lang.OutOfMemoryError: nem lehet új natív szálat létrehozni hiba

2.2. Menetallokációs modell

Egy operációs rendszer általában rendelkezik kétféle szál - felhasználói szálak (Java alkalmazás által létrehozott szálak) és kernel szálak. A felhasználói szálak a kernelszálak felett támogatottak, és a kernelszálakat az operációs rendszer kezeli.

Közöttük három közös kapcsolat van:

  1. Sok-az-egyhez - Sok felhasználói szál egyetlen kernlaphoz kapcsolódik
  2. 1-1 - Egy felhasználói szál leképezése egy kernel szálra
  3. Sok-sok-sok - Sok felhasználói szál multiplexel kisebb vagy azonos számú kernelszálhoz

3. A hiba megismétlése

Könnyen újrateremthetjük ezt a problémát, ha szálakat hozunk létre egy folyamatos ciklusban, majd várakoztatjuk a szálakat:

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

Mivel egy órán át ragaszkodunk az egyes szálakhoz, miközben folyamatosan újakat hozunk létre, gyorsan elérjük az operációs rendszer maximális szálainak számát.

4. Megoldások

A hiba elhárításának egyik módja a szálkorlát-konfiguráció növelése az operációs rendszer szintjén.

Ez azonban nem ideális megoldás, mert a OutOfMemoryError valószínűleg programozási hibát jelez. Vizsgáljuk meg a probléma megoldásának néhány más módját.

4.1. Az Executor Service Framework kihasználása

A Java végrehajtó szolgáltatási keretrendszerének felhasználása a száladminisztrációhoz bizonyos mértékben megoldhatja ezt a problémát. Az alapértelmezett végrehajtói szolgáltatási keretrendszer vagy egy egyedi végrehajtó konfiguráció vezérelheti a szálak létrehozását.

Használhatjuk a Végrehajtók # newFixedThreadPool módszer az egyszerre felhasználható szálak maximális számának beállításához:

ExecutorService végrehajtóService = Executors.newFixedThreadPool (5); Futható runnableTask = () -> {próbálkozzon a {TimeUnit.HOURS.sleep (1); } catch (InterruptedException e) {// Kivétel kezelése}}; IntStream.rangeClosed (1, 10) .forEach (i -> executorService.submit (runnableTask)); assertThat ((((ThreadPoolExecutor) executorService) .getQueue (). size (), is (equalTo (5)));

A fenti példában először egy szálas rögzített szálat hozunk létre öt szálból és egy futtatható feladattól, amely a szálakat egy órán át várja. Ezután tíz ilyen feladatot adunk be a szálkészletbe, és azt állítjuk, hogy öt feladat vár a végrehajtói szolgáltatás sorában.

Mivel a szálkészletnek öt szála van, ezért maximum öt feladatot képes bármikor kezelni.

4.2. A szálkép rögzítése és elemzése

A szállekép rögzítése és elemzése hasznos a szál állapotának megértéséhez.

Nézzünk meg egy szál lerakódást, és nézzük meg, mit tanulhatunk:

A fenti szál pillanatkép a Java VisualVM-től származik a korábban bemutatott példához. Ez a pillanatkép egyértelműen bemutatja a folyamatos szálalkotást.

Miután azonosítottuk, hogy folyamatos a szál létrehozása, rögzíthetjük az alkalmazás szálkiadását, hogy azonosítsuk a szálakat létrehozó forráskódot:

A fenti pillanatképben azonosíthatjuk a szál létrehozásáért felelős kódot. Ez hasznos betekintést nyújt a megfelelő intézkedések megtételéhez.

5. Következtetés

Ebben a cikkben megtudtuk a java.lang.OutOfMemoryError: nem lehet új natív szálat létrehozni hiba, és ezt láttuk a túlzott szálalkotás okozza Java alkalmazásban.

Felfedeztünk néhány megoldást a hiba kezelésére és elemzésére a ExecutorService a keretrendszer és a szál dump elemzés, mint két hasznos intézkedés ennek a kérdésnek a kezelésére.

Mint mindig, a cikk forráskódja elérhető a GitHubon.


$config[zx-auto] not found$config[zx-overlay] not found