web-dev-qa-db-fra.com

Java Erreur de mémoire: impossible de créer un nouveau thread natif

J'obtiens cette erreur sur mon serveur UNIX, lors de l'exécution de mon Java:

Exception in thread "Thread-0" Java.lang.OutOfMemoryError: unable to create new native thread
at Java.lang.Thread.start0(Native Method)
at Java.lang.Thread.start(Thread.Java:640)
at [... where ever I launch a new Thread ...]

Cela se produit chaque fois que j'ai environ 600 threads en cours d'exécution.

J'ai configuré cette variable sur le serveur:

$> ulimit -s 128

Ce qui me semble étrange, c'est le résultat de cette commande, que j'ai exécutée lorsque le bogue s'est produit la dernière fois:

$> free -m
              total       used       free     shared    buffers     cached
Mem:          2048        338       1709          0          0          0
-/+ buffers/cache:        338       1709
Swap:            0          0          0

Je lance mon Java comme ceci:

$> /usr/bin/Java -server -Xss128k -Xmx500m -jar /path/to/myJar.jar

Ma version Debian:

$> cat /etc/debian_version
5.0.8

Ma Java:

$> Java -version
Java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)

Ma question: j'ai lu sur Internet que mon programme devrait gérer quelque chose comme 5000 threads ou plus. Alors, que se passe-t-il et comment y remédier s'il vous plaît?


Edit: c'est la sortie de ulimit -a lorsque j'ouvre un shell:

core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 794624
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 100000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 794624
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Je lance le script en tant que démon depuis init.d, et voici ce que je lance:

DAEMON=/usr/bin/Java
DAEMON_ARGS="-server -Xss128k -Xmx1024m -jar /path/to/myJar.jar"
ulimit -s 128 && ulimit -n 10240 && start-stop-daemon -b --start --quiet --chuid $USER -m -p $PIDFILE --exec $DAEMON -- $DAEMON_ARGS \
    || return 2

Edit2: Je suis tombé sur cette question de débordement de pile avec un Java test pour les threads: combien-de-threads-peut-a-Java-vm-support

    public class DieLikeADog { 
        private static Object s = new Object(); 
        private static int count = 0; 
        public static void main(String[] argv){ 
            for(;;){ 
                new Thread(new Runnable(){ 
                        public void run(){ 
                            synchronized(s){ 
                                count += 1; 
                                System.err.println("New thread #"+count); 
                            } 
                            for(;;){ 
                                try { 
                                    Thread.sleep(100); 
                                } catch (Exception e){ 
                                    System.err.println(e); 
                                } 
                            } 
                        } 
                    }).start(); 
            } 
        } 
    } 

Sur mon serveur, le programme plante après 613 threads. Maintenant, je suis certain que ce n'est pas normal et uniquement lié à la configuration de mon serveur. Quelqu'un peut-il aider s'il vous plaît ?


Edit 3: J'ai rencontré cet article, et bien d'autres, expliquant que Linux ne peut pas créer 1000 threads , mais vous me dites que vous pouvez le faire sur vos systèmes. Je ne comprends pas.

J'ai également exécuté ce script sur mon serveur: threads_limits.c et la limite est d'environ 620 threads.

Mon site Web est maintenant hors ligne et c'est la pire chose qui puisse arriver à mon projet. Je ne sais pas comment recompiler la glibc et ce genre de choses. C'est trop de travail imo.

Je suppose que je devrais passer au serveur Windows. Parce qu'aucun des paramètres proposés sur cette page n'a apporté de changement: la limite sur mon système est comprise entre 600 et 620 threads, quel que soit le programme impliqué.

25
Joel

Je viens de recevoir les informations suivantes: Il s'agit d'une limitation imposée par mon fournisseur d'hébergement. Cela n'a rien à voir avec la programmation ou Linux.

12
Joel

Le système d'exploitation sous-jacent (Debian Linux dans ce cas) ne permet pas au processus de créer plus de threads. Voir ici comment augmenter le montant maximum: Nombre maximum de threads par processus sous Linux?

J'ai lu sur Internet que mon programme devrait gérer quelque chose comme 5000 threads ou plus.

Cela dépend des limites définies pour le système d'exploitation, de la quantité de processus en cours d'exécution, etc. Avec des paramètres corrects, vous pouvez facilement atteindre autant de threads. J'utilise Ubuntu sur mon propre ordinateur, et je peux créer environ 32000 threads avant d'atteindre la limite sur un seul programme Java avec toutes mes "trucs normaux" en arrière-plan (cela a été fait avec un programme de test qui vient de créer des threads qui se sont immédiatement mis en veille dans une boucle infinie.) Naturellement, cette quantité élevée de threads faisant réellement quelque chose entraînerait probablement l'arrêt rapide du matériel grand public.

7
esaj

Pouvez-vous essayer la même commande avec une taille de pile plus petite "-Xss64k" et transmettre les résultats?

3
souser

Je commence à soupçonner que "Native Posix Thread Library" est manquante.

>getconf GNU_LIBPTHREAD_VERSION

Devrait produire quelque chose comme:

NPTL 2.13

Sinon, l'installation de Debian est foirée. Je ne sais pas comment résoudre ce problème, mais l'installation d'Ubuntu Server semble être une bonne chose ...

pour ulimit -n 100000; (open fd: s) le programme suivant devrait être capable de gérer environ 32 000 threads.

Essayez-le:

package test;

import Java.io.InputStream;
import Java.net.ServerSocket;
import Java.net.Socket;
import Java.util.ArrayList;
import Java.util.concurrent.Semaphore;

public class Test {

    final static Semaphore ss = new Semaphore(0);


    static class TT implements Runnable {

        @Override
        public void run() {
            try {
                Socket t = new Socket("localhost", 47111);
                InputStream is = t.getInputStream();
                for (;;) {
                    is.read();
                }

            } catch (Throwable t) {
                System.err.println(Thread.currentThread().getName() + " : abort");
                t.printStackTrace();
                System.exit(2);
            }

        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {

            Thread t = new Thread() {
                public void run() {
                    try {
                        ArrayList<Socket> sockets = new ArrayList<Socket>(50000);
                        ServerSocket s = new ServerSocket(47111,1500);
                        ss.release();

                        for (;;) {
                            Socket t = s.accept();
                            sockets.add(t);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        System.exit(1);

                    }
                }
            };


            t.start();
            ss.acquire();


            for (int i = 0; i < 30000; i++) {

                Thread tt = new Thread(new TT(), "T" + i);
                tt.setDaemon(true);
                tt.start();
                System.out.println(tt.getName());
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    return;
                }
            }

            for (;;) {
                System.out.println();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    return;
                }
            }

        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}
2
KarlP

Votre JVM ne parvient pas à allouer la pile ou une autre mémoire par thread. Réduire la taille de la pile avec -Xss Aidera à augmenter le nombre de threads que vous pouvez créer avant que le MOO ne se produise (mais la JVM ne vous permettra pas de définir une taille de pile arbitrairement petite).

Vous pouvez confirmer que c'est le problème en voyant comment le nombre de threads créés change lorsque vous ajustez -Xss Ou en exécutant strace sur votre JVM (vous verrez presque certainement une fonction mmap() renvoyant ENOMEM juste avant qu'une exception ne soit levée).

Vérifiez également votre ulimit sur la taille virtuelle, c'est-à-dire ulimit -v. L'augmentation de cette limite devrait vous permettre de créer plus de threads avec la même taille de pile. Notez que la limite de taille de l'ensemble résident (ulimit -m) Est inefficace dans le noyau Linux actuel .

En outre, réduire -Xmx Peut aider en laissant plus de mémoire pour les piles de threads.

1
Adam Zalcman