Orien правильний, це системний виклик fork (), ініційований ProcessBuilder або Runtime.exec або іншими засобами JVM, виконуючи зовнішній процес (наприклад, інший запущений мурашник JVM, команда git тощо).
У списках розсилки Дженкінса про це були деякі повідомлення: Неможливо запустити програму "git" ... помилка = 12, Неможливо виділити пам'ять
У списку розробників SCons є приємний опис випуску: fork () + exec () vs posix_spawn ()
Існує давній звіт про помилки JVM з рішеннями: Використовуйте posix_spawn, а не вилку, на S10, щоб уникнути виснаження свопів . Але я не впевнений, чи це насправді ввійшло в JDK7, як підказують коментарі.
Підсумовуючи це, у Unix-подібних системах, коли одному процесу (наприклад, JVM) потрібно запустити інший процес (наприклад, git), робиться системний виклик, fork()
який ефективно дублює поточний процес і всю його пам'ять (Linux та інші оптимізують це за допомогою копії -напишіть, щоб пам'ять насправді не була скопійована, поки дитина не спробує записати на неї). Потім дублюючий процес робить інший системний виклик, exec()
щоб запустити інший процес (наприклад, git), і тоді вся операція, що скопіювала пам'ять з батьківського процесу, може бути відкинута операційною системою. Якщо батьківський процес використовує велику кількість пам’яті (як це робиться в процесах JVM), виклик fork()
може не вдатися, якщо операційна система визначить, що у нього не вистачає пам’яті + своп для зберігання двох копій, навіть якщо дочірній процес ніколи насправді не буде використовувати цю скопійовану пам'ять.
Є кілька рішень:
Додайте в машину більше фізичної пам’яті / оперативної пам’яті.
Додайте більше місця для заміни, щоб ввести fork()
в роботу, навіть якщо простір для заміни строго не потрібен ні для чого. Це рішення, яке я вибрав, тому що додати свопфайл досить просто, і я не хотів жити з можливістю вбивати процеси через перевиконання.
В Linux ввімкніть overcommit_memory
опцію системи vm ( / proc / sys / vm / overcommit_memory ). З надмірним доступом, заклик до fork()
цього завжди буде успішним, і оскільки дочірній процес насправді не збирається використовувати цю копію пам'яті, все добре. Звичайно, можливо, що при надмірній передачі, ваші процеси будуть намагатися використовувати більше пам'яті, ніж доступно, і буде вбито ядром. Наскільки це підходить, залежить від інших застосувань машини. Машини з критичною місією, ймовірно, не повинні загрожувати вбивці поза пам'яттю під керуванням amok. Але внутрішній сервер розробки, який може дозволити собі час простою, був би хорошим місцем для включення перевиконання.
Змініть JVM не використовувати fork()
+, exec()
але використовувати, posix_spawn()
коли є. Це рішення, яке вимагається у звіті про помилки JVM вище та згадується у списку розсилки SCons. Він також реалізований у java_posix_spawn .
Я намагаюся з’ясувати, чи виправили це виправлення в JDK7. Якщо ні, то мені цікаво, чи цікавили б люди Дженкінса такі роботи, як, наприклад, java_posix_spawn. Здається, були спроби інтегрувати це в Apache commons-exec .
Programmieraffe, я не впевнений на 100%, але ваше посилання говорить про те, що виправлення є в JDK7 та JDK6 1.6.0_23 та пізніших версіях. Для запису я працював OpenJDK 1.6.0_18.
Дивіться /programming/1124771/how-to-solve-java-io-ioexception-error-12-cannot-allocate-memory-calling-run