"java.lang.OutOfMemoryError: невозможно создать новый собственный поток"

Мы получаем "java.lang.OutOfMemoryError : unable to create new native Thread "на 8 ГБ ОЗУ VM после потоков 32k (ps -eLF | grep -c java)

Однако "top" and "free -m" shows 50% free memory available. JDk имеет 64-битную версию и работает как с HotSpot, так и с JRockit.Server с Linux 2.6.18

Мы также пробовали OS stack size (ulimit -s) настройки и максимальный процесс (ulimit -u), limit.conf, но все напрасно.

Также мы попытались почти все возможные комбинации размеров кучи, сохраняя его низким, высоким и т.д.

script, который мы используем для запуска приложения,

/opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m -Xss128k -jar JavaNatSimulator.jar /opt/tools/jnatclients/natSimulator.properties

Спасибо за ответ.

Мы попытались отредактировать /etc/security/limits.conf и ulimit, но все же этот же

[[email protected] ~]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 72192
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
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) 72192
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Ответ 1

Это не проблема с памятью, хотя имя исключения настоятельно рекомендует, а проблема с ресурсами операционной системы. У вас заканчиваются собственные потоки, то есть сколько потоков операционная система разрешит использовать вашей JVM.

Это необычная проблема, потому что вам редко нужно столько. У вас есть много безусловных потоков, где потоки должны, но не заканчиваются?

Вы можете рассмотреть возможность переписывания в Callable/Runnables под контролем исполнителя, если это вообще возможно. Существует множество стандартных исполнителей с различным поведением, которыми ваш код может легко управлять.

(Есть много причин, по которым количество потоков ограничено, но они варьируются от операционной системы к операционной системе)

Ответ 2

Вероятно, ваша ОС не разрешает количество потоков, которые вы пытаетесь создать, или вы нажимаете некоторый предел в JVM. Особенно, если такой круглый номер, равный 32k, предел того или иного вида является очень вероятным виновником.

Вам действительно нужны 32k темы? Большинство современных языков имеют некоторую поддержку для пулов многоразовых потоков - я уверен, что у Java есть что-то на месте (например, ExecutorService, как упоминал пользователь Jesper). Возможно, вы могли бы запрашивать потоки из такого пула, а не вручную создавать новые.

Ответ 3

Я столкнулся с той же проблемой во время нагрузочного теста, причина в том, что JVM не может дальше создавать новый поток Java. Ниже приведен исходный код JVM

if (native_thread->osthread() == NULL) {    
// No one should hold a reference to the 'native_thread'.    
    delete native_thread;   
if (JvmtiExport::should_post_resource_exhausted()) {      
    JvmtiExport::post_resource_exhausted(        
        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | 
        JVMTI_RESOURCE_EXHAUSTED_THREADS, 
        "unable to create new native thread");    
    } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "unable to create new native thread");  
} Thread::start(native_thread);'

Основная причина: JVM выдает это исключение, когда JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR (ресурсы исчерпаны (означает, что память исчерпана)) или JVMTI_RESOURCE_EXHAUSTED_THREADS (потоки исчерпаны).

В моем случае Jboss создает слишком много потоков для обслуживания запроса, но все потоки заблокированы. Из-за этого JVM исчерпывается потоками, а также памятью (каждый поток содержит память, которая не освобождается, потому что каждый поток заблокирован).

Проанализировано, что дампы Java-потоков обнаружили, что почти 61K-потоки заблокированы одним из наших методов, который вызывает эту проблему. Ниже приведена часть дампа темы

"SimpleAsyncTaskExecutor-16562" #38070 prio=5 os_prio=0 tid=0x00007f9985440000 nid=0x2ca6 waiting for monitor entry [0x00007f9d58c2d000]
   java.lang.Thread.State: BLOCKED (on object monitor)

Ответ 4

Я бы порекомендовал также посмотреть размер стека и посмотреть, есть ли у вас больше созданных потоков. Размер стека по умолчанию для JRockit 1.5/1.6 - 1 МБ для 64-разрядной виртуальной машины в ОС Linux. Для выполнения этого требования потоки 32K потребуют значительного количества физической и виртуальной памяти.

Попробуйте уменьшить размер стека до 512 КБ в качестве отправной точки и посмотреть, помогает ли оно создавать больше потоков для вашего приложения. Я также рекомендую изучить горизонтальное масштабирование, например. разделяя обработку приложений на более физических или виртуальных машинах.

При использовании 64-разрядной виртуальной машины истинный предел будет зависеть от доступности физической и виртуальной памяти ОС и параметров настройки ОС, таких как ulimitc. Я также рекомендую следующую статью в качестве ссылки:

OutOfMemoryError: не удается создать новый собственный поток - проблема Demystified

Ответ 5

У меня была та же проблема из-за призрачных процессов, которые не отображались при использовании top в bash. Это предотвратило появление JVM больше потоков.

Для меня это разрешилось при перечислении всех java-процессов с помощью jps (просто выполните jps в своей оболочке) и убили их отдельно используя команду kill -9 pid bash для каждого призрачного процесса.

Это может помочь в некоторых сценариях.

Ответ 6

Если ваше задание терпит неудачу из-за OutOfMemmory на узлах, вы можете tweek количество максимальных карт и редукторов, а выбор JVM для каждого. mapred.child.java.opts(значение по умолчанию - 200Xmx) обычно должно быть увеличено на основе ваших конкретных узлов данных.

Эта ссылка может быть полезна... pls check

Ответ 7

у вашей конфигурации JBoss есть некоторые проблемы, /opt/jrockit -jdk1.6/bin/java -Xms512m -Xmx512m Xms и Xmx ограничивают использование вашей памяти JBoss до заданного значения, поэтому из 8Gb у вас есть сервер, который использует только 512M + для некоторых других целей, увеличивая это число, не забудьте оставить некоторые бесплатно для ОС и других вещей там работает, и вы можете запустить его, несмотря на неприятный код. Исправить код тоже было бы неплохо, если можно.

Ответ 8

У вас есть возможность столкнуться с java.lang.OutOfMemoryError: Unable to create new native thread, когда JVM запрашивает новый поток из ОС. Всякий раз, когда базовая ОС не может выделять новый собственный поток, это OutOfMemoryError будет выбрано. Точный предел для собственных потоков очень зависит от платформы, поэтому рекомендуется выяснить эти ограничения, выполнив тест, аналогичный приведенному ниже примеру ссылки. Но, в общем, ситуация, вызывающая java.lang.OutOfMemoryError: Unable to create new native thread, проходит через следующие фазы:

  • Новый поток Java запрашивается приложением, запущенным внутри JVM
  • Собственный код JVM проксирует запрос на создание нового родного поток в ОС ОС пытается создать новый собственный поток, который требуется выделение памяти для потока
  • ОС откажется нативного распределения памяти либо потому, что 32-разрядный размер Java-процесса истощило адресное пространство памяти - например, (2-4) размер процесса GB предел был удален - или виртуальная память ОС была полностью истощенный
  • java.lang.OutOfMemoryError: невозможно создать новый родной ошибка потока.

Ссылка: https://plumbr.eu/outofmemoryerror/unable-to-create-new-native-thread

Ответ 9

У меня была эта же проблема, и оказалось, что это неправильное использование java API. Я инициализировал построитель в методе пакетной обработки, который не должен быть инициализирован более одного раза.

В основном я делал что-то вроде:

for (batch in batches) {
    process_batch(batch)
}

def process_batch(batch) {
    var client = TransportClient.builder().build()
    client.processList(batch)
}

когда я должен был это сделать:

for (batch in batches) {
    var client = TransportClient.builder().build()
    process_batch(batch, client)
}

def process_batch(batch, client) {
    client.processList(batch)
}

Ответ 10

Чтобы узнать, какие процессы создают потоки, попробуйте:

ps huH

Я обычно перенаправляю вывод в файл и анализирую файл в автономном режиме (количество потоков для каждого процесса соответствует ожидаемому или нет)

Ответ 11

Эта ошибка может появиться из-за следующих двух причин:

  • В памяти нет места для размещения новых тем.

  • Количество потоков превышает ограничение операционной системы.

Я сомневаюсь, что количество потоков превысило ограничение для процесса Java

Так что, вероятно, проблема в том, что из-за памяти

потоки не создаются в куче JVM. Они созданы вне кучи JVM. Поэтому, если в ОЗУ осталось меньше места, после выделения кучи JVM приложение столкнется с "java.lang.OutOfMemoryError: не удалось создать новый собственный поток".

Возможное решение - уменьшить память кучи или увеличить общий размер оперативной памяти.

Ответ 12

Прежде всего, я бы не стал винить в этом OS OS/VM.. скорее разработчик, который написал код, который создает sooo many Threads. В основном где-то в вашем коде (или стороннем) создано множество потоков без управления.

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