Низкое ограничение количества потоков Java в Red Hat Linux

У меня возникла проблема на тестовой машине с Red Hat Linux (версия ядра 2.4.21-37.ELsmp) с Java 1.6 (1.6.0_02 или 1.6.0_04). Проблема в том, что как только определенное количество потоков создается в одной группе потоков, операционная система не желает или не может создавать больше.

Кажется, это характерно для Java, создающего потоки, поскольку программа ограничения потоков C смогла создать около 1,5 тыс. Потоков. Кроме того, этого не происходит с Java 1.4 JVM ... она может создавать более 1,4 тыс. Потоков, хотя, очевидно, они обрабатываются по-разному в зависимости от ОС.

В этом случае количество нитей, на которых она обрезается, составляет всего 29 ниток. Это можно проверить с помощью простой программы на Java, которая просто создает потоки до тех пор, пока не получит сообщение об ошибке, а затем распечатает количество созданных потоков. Ошибка - это

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

Похоже, на это не влияют такие вещи, как количество потоков, используемых другими процессами или пользователями, или общий объем памяти, который система использует в данный момент. Настройки JVM, такие как Xms, Xmx и Xss, похоже, тоже ничего не меняют (что и ожидается, учитывая, что проблема, похоже, связана с созданием собственного потока ОС).

Вывод «ulimit -a» выглядит следующим образом:

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

Ограничение пользовательского процесса, похоже, не проблема. Поиск информации о том, что может быть неправильным, не принес особого успеха, но эта почта, похоже, указывает на то, что по крайней мере некоторые ядра Red Hat ограничивают процесс до 300 МБ памяти, выделенной для стека, и 10 МБ на поток для стека, похоже проблема могла быть там (хотя это тоже кажется странным и маловероятным).

Я попытался изменить размер стека с помощью «ulimit -s», чтобы проверить это, но любое значение, кроме 10240, и JVM не запускается с ошибкой:

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

Обычно я могу обойти Linux, но я действительно мало знаю о конфигурации системы, и мне не удалось найти ничего, специально предназначенного для такого рода ситуаций. Приветствуются любые идеи о том, какая система или настройки JVM могут вызывать это.

Правки: при запуске программы ограничения потоков, упомянутой в цоколь, сбоев не было, пока она не попыталась создать 1529-й поток.

Проблема также не возникала при использовании JVM 1.4 (действительно возникает с JVM 1.6.0_02 и 1.6.0_04, на данный момент невозможно протестировать с 1.5 JVM).

Код для теста потока, который я использую, выглядит следующим образом:

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) {
         }
      }
   }
}

Если вы запустите это с 1.4 JVM, он зависнет, когда не сможет создать больше потоков и потребует kill -9 (по крайней мере, для меня).

Больше редактировать:

Оказывается, система, в которой возникла проблема, использует модель потоковой передачи LinuxThreads, в то время как другая система, которая работает нормально, использует модель NPTL.

просто небольшая заметка для всех начинающих программистов: никогда не используйте while(true) где-либо, кроме школьных проектов и частных экспериментов, а НИКОГДА создает тысячи потоков, ваше приложение, скорее всего, имеет серьезные ошибки, если оно есть, - иначе дизайн вашего приложения ошибочен . Просто говорю ..

specializt 16.01.2015 14:51
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
7
1
18 259
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Вы смотрели этот ресурс? В нем говорится, что вы должны иметь возможность запускать thread-limit, чтобы найти максимальное количество потоков, и можете настроить его, скомпилировав glibc.

Как ни странно, thread-limit смог создать 1528 потоков до сбоя. Хм.

ColinD 22.09.2008 23:00

Это с Ubuntu Linux (1 ГБ ОЗУ)

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:~$ 

Можете ли вы попробовать это с JRockit JVM? IIRC, у него была другая модель потоковой передачи, чем у стандартной Sun JVM.

Ответ принят как подходящий

Обновление ядра до более новой версии (2.6.something) с потоковой передачей NPTL исправило это.

Настройки /etc/security/limits.d/90-nproc.conf могут иметь приоритет над настройками /etc/security/limits.conf. Это может привести к тому, что система будет действовать иначе, как показано в ulimit -u.

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

Другие вопросы по теме