Question

Je rencontre un problème sur une machine de test exécutant Red Hat Linux (la version du noyau est 2.4.21-37.ELsmp) avec Java 1.6 (1.6.0_02 ou 1.6.0_04). Le problème est qu’une fois qu’un certain nombre de threads sont créés dans un seul groupe de threads, le système d’exploitation refuse ou ne peut plus en créer.

Cela semble être spécifique à la création de threads Java, car le programme C-thread-limit a pu créer environ 1,5k threads. De plus, cela ne se produit pas avec une machine virtuelle Java Java 1.4 ... elle peut créer des threads de plus de 1,4k, bien qu'ils soient évidemment gérés différemment par rapport au système d'exploitation.

Dans ce cas, le nombre de threads à couper est de 29 fils. Ceci est testable avec un simple programme Java qui crée des threads jusqu'à ce qu'il y ait une erreur, puis affiche le nombre de threads créés. L'erreur est un

java.lang.OutOfMemoryError: unable to create new native thread

Cela ne semble pas être affecté par des facteurs tels que le nombre de threads utilisés par d'autres processus ou utilisateurs ou la quantité totale de mémoire utilisée par le système à ce moment-là. Les paramètres JVM tels que Xms, Xmx et Xss ne semblent rien changer non plus (ce qui est prévu, étant donné que le problème semble être lié à la création de threads de système d'exploitation natif).

La sortie de "ulimit -a" est comme suit:

core file size        (blocks, -c) 0
data seg size         (kbytes, -d) unlimited
file size             (blocks, -f) unlimited
max locked memory     (kbytes, -l) 4
max memory size       (kbytes, -m) unlimited
open files                    (-n) 1024
pipe size          (512 bytes, -p) 8
stack size            (kbytes, -s) 10240
cpu time             (seconds, -t) unlimited
max user processes            (-u) 7168
virtual memory        (kbytes, -v) unlimited

La limite du processus utilisateur ne semble pas être le problème. La recherche d'informations sur ce qui pourrait être erroné n'a pas donné beaucoup de résultats, mais cet article semble indiquer qu'au moins certains noyaux Red Hat limitent un processus à 300 Mo de mémoire allouée pour la pile, et à 10 Mo par thread pour la pile, il semble que le problème pourrait être là (bien que cela semble étrange et peu probable bien).

J'ai essayé de modifier la taille de la pile avec "ulimit -s". pour le tester, mais toute valeur autre que 10240 et que la machine virtuelle Java ne commence pas par une erreur de:

Error occurred during initialization of VM
Cannot create VM thread. Out of system resources.

Je peux généralement contourner Linux, mais je ne connais pas grand-chose à la configuration du système et je n’ai rien trouvé qui réponde précisément à ce type de situation. Toute idée sur les paramètres système ou JVM pouvant être à l'origine de cette situation serait la bienvenue.

Modifications : exécution du programme de thread-limit mentionné par plinth , il n'y a pas eu d'échec tant qu'il n'a pas essayé de créer le 1529ème thread.

Le problème ne s'est pas non plus produit avec une machine virtuelle Java 1.4 (se produit avec les machines virtuelles 1.6.0_02 et 1.6.0_04, impossible de tester avec une machine virtuelle Java 1.5 pour le moment).

Le code du test de thread que j'utilise est le suivant:

public class ThreadTest {

   public static void main(String[] pArgs) throws Exception {

      try {
         // keep spawning new threads forever
         while (true) {
            new TestThread().start();
         }
      }
      // when out of memory error is reached, print out the number of
      // successful threads spawned and exit
      catch ( OutOfMemoryError e ) {
         System.out.println(TestThread.CREATE_COUNT);
         System.exit(-1);
      }
   }

   static class TestThread extends Thread {
      private static int CREATE_COUNT = 0;
      public TestThread() {
         CREATE_COUNT++;
      }
      // make the thread wait for eternity after being spawned
      public void run() {
         try {
            sleep(Integer.MAX_VALUE);
         }
         // even if there is an interruption, dont do anything
         catch (InterruptedException e) {
         }
      }
   }
}

Si vous exécutez ceci avec une machine virtuelle Java 1.4, il se bloquera s'il ne peut plus créer de threads et nécessite un kill -9 (du moins, il l'a fait pour moi).

Plus de modifications:

Il s'avère que le système qui rencontre le problème utilise le modèle de thread LinuxThreads alors qu'un autre système qui fonctionne correctement utilise le modèle NPTL.

Était-ce utile?

La solution 2

La mise à jour du noyau vers une version plus récente (2.6.quelque chose) avec le threading NPTL a résolu ce problème.

Autres conseils

Avez-vous consulté cette ressource ? Il indique que vous devriez pouvoir exécuter thread-limit pour trouver le nombre maximal de threads et le modifier en compilant la glibc.

C’est avec Ubuntu Linux (1 Go de RAM)

dsm@localhost:~$ javac ThreadTest.java 
dsm@localhost:~$ java ThreadTest 
8113
dsm@localhost:~$ java -version
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)
dsm@localhost:~$ 

Pouvez-vous l’essayer avec la JVM JRockit? IIRC, son modèle de threading était différent de celui de la JVM Sun Sun stock.

Les paramètres de /etc/security/limits.d/90-nproc.conf peuvent remplacer vos paramètres /etc/security/limits.conf . Cela peut entraîner une réaction différente du système, comme indiqué dans ulimit -u .

https://bugzilla.redhat.com/show_bug.cgi?id=823030

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top