"Java.lang.OutOfMemoryError: не вдається створити нову рідну нитку"


124

Ми отримуємо "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, але все даремно.

Також ми спробували майже всі можливі комбінації розмірів купи, зберігаючи її низький, високий тощо.

Сценарій, який ми використовуємо для запуску програми

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

Дякую за відповідь.

Ми спробували редагувати /etc/security/limits.conf та ulimit, але все одно те саме

[root@jboss02 ~]# 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

11
Операційні системи мають обмеження щодо кількості потоків, які ви можете створити. Чому ви створюєте більше 32-х потоків? У вашій системі, швидше за все, немає тисяч процесорних ядер, створювати стільки потоків не корисно. Використовуйте ExecutorServiceзамість пулу потоків ( ).
Джеспер

Дякую за відповідь. Ми використовуємо бібліотеку з відкритим кодом і намагаємося завантажити тест. Будь-яка бібліотека з відкритим кодом створює стільки потоків. Але те, що я не розумію, це те, коли "зверху" показує 50% вільної пам'яті, то чому помилка OutOfMemory.
Діпак Тевані

Бібліотека з відкритим кодом, яку ми використовуємо в бібліотеці ICE4j
Deepak Tewani,

11
OutOfMemoryError не обов'язково означає, що обширний простір, або "загальна" ОЗУ була вичерпана. У цьому випадку зрозуміло, що збій стався через те, що ОС не мала ресурсів виділити додатковий потік. Наявність 50% вільної пам’яті не має значення для цього конкретного поломки.
Анджей Дойл

1
Які ще ресурси потрібні для створення нових тем. У нас було враження, що якщо ми збільшимо оперативну пам’ять, то, можливо, ми зможемо створити більше потоків.
Просьба

Відповіді:


80

Це не проблема пам’яті, навіть якщо назва винятку дуже напрошується, а проблема ресурсу операційної системи. У вас закінчуються власні потоки, тобто скільки потоків операційна система дозволить використовувати ваш JVM.

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

Ви можете розглянути можливість перезапису на використання Callable / Runnables під контролем Виконавця, якщо це можливо. Є безліч стандартних виконавців з різною поведінкою, кодом можна легко керувати.

(Є багато причин, через які кількість потоків обмежена, але вони різняться від операційної системи до операційної системи)


Дякую за відповідь. Ми використовуємо бібліотеку з відкритим кодом ICE4j і намагаємося завантажити тест. Не можемо збільшити ліміт потоків в ОС, коли ми знаємо, що на сервері залишилось 50% пам'яті.
Діпак Тевані

Можливо, але я думаю, що це вам не допоможе. Якщо у вас не вистачає ресурсів під час тестування завантаження, ви повинні мати можливість контролювати те, що відбувається у вашій програмі. Чому у вас активовано 32000 ниток одночасно?
Thorbjørn Ravn Andersen

Ми створюємо 11K клієнтів, які використовують 32 K потоки для читання, запису даних у UDP-розетки. Із цих 32-кілограмових потоків нитки 10К зберігають живі нитки, які використовуються для збереження розетки
Deepak Tewani

Я вважаю, що ця проблема вирішена на сучасних веб-серверах. Також udp може втратити пакети - з якої причини ви не просто використовуєте веб-сервер?
Thorbjørn Ravn Andersen

7
Тому що виняток OutOfMemory повинен був бути названий OutOfResources. Операційна система не може забезпечити потрібний вам ресурс. (І виявилося, що я не знаю ice4j)
Thorbjørn Ravn Andersen

14

Я зіткнувся з тією ж проблемою під час тесту навантаження, тому що 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 вичерпується потоками, а також пам'яттю (кожен потік містить пам'ять, яка не вивільняється, оскільки кожен потік заблокований).

Проаналізовані відвали явових ниток, які спостерігаються майже 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)

Як було заблоковано метод? Ніколи не повертається?
Thorbjørn Ravn Andersen

8

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

Ви впевнені, що вам справді потрібні 32K нитки? У більшості сучасних мов є якась підтримка для пулів багаторазових потоків - я впевнений, що у Java теж є щось на своєму місці (наприклад ExecutorService, як згадував користувач Jesper). Можливо, ви можете попросити теми з такого пулу, а не створювати нові вручну.


1
Дякуємо за відповідь. Ми використовуємо бібліотеку з відкритим кодом ICE4j і намагаємося завантажити тест. Не можемо збільшити ліміт потоків в ОС, коли ми знаємо, що на сервері залишилось 50% пам'яті.
Діпак Тевані

1
Ми створюємо 11K клієнтів, які використовують 32 K потоки для читання, запису даних у UDP-розетки. Із цих 32-кілограмових потоків нитки 10К зберігають живі нитки, які використовуються для утримання розетки
Deepak Tewani

7

Я рекомендую також переглянути розмір стеки ниток і побачити, чи створено більше тем. За замовчуванням розмір стека нитки для JRockit 1.5 / 1.6 становить 1 Мб для 64-бітної VM в ОС Linux. 32K потокам знадобиться значна кількість фізичної та віртуальної пам'яті, щоб виконати цю вимогу.

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

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

OutOfMemoryError: не вдається створити нову рідну нитку - проблема демістифікована


5

Якщо jvm запускається через systemd, в деяких операційних системах Linux може бути максимальна кількість завдань на обмеження процесу (завдання фактично означають потоки).

Ви можете перевірити це, запустивши "статус сервісу" та перевірити, чи існує обмеження maxTasks. Якщо є, ви можете видалити його, відредагувавши /etc/systemd/system.conf, додавши конфігурацію: DefaultTasksMax = нескінченність


3

У мене була така ж проблема через привидні процеси, які не з’являлися при використанні верху в баші. Це завадило JVM породити більше ниток.

Для мене це вирішено, коли перераховуються всі процеси Java з jps (просто виконайте jpsу своїй оболонці) та вбиваєте їх окремо, використовуючи команду kill -9 pidbash для кожного процесу привидів.

Це може допомогти в деяких сценаріях.


2

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

  1. Новий потік Java запитується програмою, що працює всередині JVM
  2. Народний код JVM надає просьбу створити нову основну нитку для ОС. ОС намагається створити новий власний потік, який потребує виділення пам'яті для потоку.
  3. ОС відмовиться від розподілу нативного пам'яті або тому, що розмір 32-бітного процесу Java вичерпав простір адреси пам'яті - наприклад, (2-4) ГБ обмеження обсягу процесу було досягнуто - або віртуальна пам'ять ОС повністю виснажена
  4. Java.lang.OutOfMemoryError: Не вдається створити нову нативну помилку.

Довідка: https://plumbr.eu/outofmemoryerror/unable-to-create-new-native-thread


2

Щоб знайти, які процеси створюють теми, спробуйте:

ps huH

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


1

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

Це посилання може бути корисним ... перевірити, будь ласка


1
Усі ми вже пробували ту зміну, яка вказана на цьому посиланні. Але результат той самий :(
Deepak Tewani

1

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


1

Ця помилка може виникнути через дві причини:

  • У пам'яті немає місця для вміщення нових тем.

  • Кількість потоків перевищує ліміт Операційної системи.

Я сумніваюся, що кількість потоків перевищила межу для процесу java

Таким чином, можливо, ймовірність проблеми полягає в пам’яті. Один момент, який слід враховувати

потоки не створюються в межах купі JVM. Вони створюються поза купою JVM. Отже, якщо в оперативній пам’яті залишилося менше місця, після розподілу купі JVM додаток запуститься в „java.lang.OutOfMemoryError: не в змозі створити новий власний потік”.

Можливе рішення - зменшити об'єм пам'яті або збільшити загальний розмір оперативної пам'яті


0

У мене був цей самий випуск, і виявилося, що це неправильне використання API Java. Я ініціалізував будівельника методом пакетної обробки, який не повинен був ініціалізуватися більше одного разу.

В основному я робив щось на кшталт:

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

-4

Перш за все я б не звинувачував стільки OS / VM .. скоріше розробника, який написав код, який створює так багато Threads . В основному десь у вашому коді (або третьої сторони) безліч потоків створюється без контролю .

Уважно перегляньте стеки / код і контролюйте кількість створених потоків. Зазвичай вашій програмі не потрібно велика кількість потоків, якщо це вже інша проблема.


10
Це не є вирішенням питання.
ftrujillo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.