Как решить "java.io.IOException: ошибка = 12, Невозможно выделить память" вызов Runtime # exec()?

В моей системе я не могу запустить простое Java-приложение, которое запускает процесс. Я не знаю, как решить.

Не могли бы вы дать мне подсказки, как решить?

Программа:

[[email protected] sisma-acquirer]# cat prova.java
import java.io.IOException;

public class prova {

   public static void main(String[] args) throws IOException {
        Runtime.getRuntime().exec("ls");
    }

}

Результат:

[[email protected] sisma-acquirer]# javac prova.java && java -cp . prova
Exception in thread "main" java.io.IOException: Cannot run program "ls": java.io.IOException: error=12, Cannot allocate memory
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:474)
        at java.lang.Runtime.exec(Runtime.java:610)
        at java.lang.Runtime.exec(Runtime.java:448)
        at java.lang.Runtime.exec(Runtime.java:345)
        at prova.main(prova.java:6)
Caused by: java.io.IOException: java.io.IOException: error=12, Cannot allocate memory
        at java.lang.UNIXProcess.<init>(UNIXProcess.java:164)
        at java.lang.ProcessImpl.start(ProcessImpl.java:81)
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:467)
        ... 4 more

Конфигурация системы:

[[email protected] sisma-acquirer]# java -version
java version "1.6.0_0"
OpenJDK Runtime Environment (IcedTea6 1.5) (fedora-18.b16.fc10-i386)
OpenJDK Client VM (build 14.0-b15, mixed mode)
[[email protected] sisma-acquirer]# cat /etc/fedora-release
Fedora release 10 (Cambridge)

EDIT: решение Это решает мою проблему, я не знаю точно, почему:

echo 0 > /proc/sys/vm/overcommit_memory

Up-votes для тех, кто может объяснить:)

Дополнительная информация, верхний вывод:

top - 13:35:38 up 40 min,  2 users,  load average: 0.43, 0.19, 0.12
Tasks: 129 total,   1 running, 128 sleeping,   0 stopped,   0 zombie
Cpu(s):  1.5%us,  0.5%sy,  0.0%ni, 94.8%id,  3.2%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   1033456k total,   587672k used,   445784k free,    51672k buffers
Swap:  2031608k total,        0k used,  2031608k free,   188108k cached

Дополнительная информация, свободный выход:

[[email protected] sisma-acquirer]# free
             total       used       free     shared    buffers     cached
Mem:       1033456     588548     444908          0      51704     188292
-/+ buffers/cache:     348552     684904
Swap:      2031608          0    2031608

Ответ 1

Каков профиль памяти вашей машины? например если вы запустите top, сколько свободной памяти у вас есть?

Я подозреваю, что UnixProcess выполняет a fork(), и он просто не получает достаточного количества памяти из ОС (если память обслуживается, он будет fork() дублировать процесс, а затем exec(), чтобы запустить ls в новом памяти, и это не доходит до этого)

EDIT: Re. ваше решение overcommit, оно позволяет переопределять системную память, что позволяет процессам распределять (но не использовать) больше памяти, чем доступно на самом деле. Поэтому я предполагаю, что fork() дублирует память процесса Java, как описано в комментариях ниже. Конечно, вы не используете память, так как "ls" заменяет повторяющийся процесс Java.

Ответ 2

Это решение, но вы должны установить:

echo 1 > /proc/sys/vm/overcommit_memory

Ответ 3

Runtime.getRuntime().exec выделяет процесс с тем же объемом памяти, что и основной. Если у вас была куча, установленная в 1 ГБ, и попробуйте выполнить exec, тогда она выделит еще 1 ГБ для запуска этого процесса.

Ответ 6

Я решил это с помощью JNA: https://github.com/twall/jna

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

public class prova {

    private interface CLibrary extends Library {
        CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
        int system(String cmd);
    }

    private static int exec(String command) {
        return CLibrary.INSTANCE.system(command);
    }

    public static void main(String[] args) {
        exec("ls");
    }
}

Ответ 7

Если вы посмотрите на источник java.lang.Runtime, вы увидите exec finally call protected method: execVM, что означает, что он использует виртуальную память. Таким образом, для Unix-подобной системы VM зависит от количества пространства подкачки + некоторого соотношения физической памяти.

Ответ Майкла разрешил вашу проблему, но он мог (или, скажем, в конечном итоге) вызвать O.S. тупик в вопросе распределения памяти, поскольку 1 рассказать O.S. менее осторожны в распределении памяти, а 0 просто догадывается и, очевидно, вам повезло, что O.S. Угадайте, у вас может быть память ЭТОТ ВРЕМЯ. В следующий раз? Хм.....

Лучший подход заключается в том, что вы экспериментируете с вашим делом и предоставляете хорошее пространство подкачки и получаете лучшее соотношение используемой физической памяти и задаете значение 2, а не 1 или 0.

Ответ 8

overcommit_memory

Управляет перекомпоновкой системной памяти, что позволяет процессам распределять (но не использовать) больше памяти, чем доступно на самом деле.

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

1 - Всегда перекомпилировать. Подходит для некоторых научных приложений.

2 - Не перекомпилируйте. Суммарному фиксации адресного пространства для системы не разрешается превышать своп плюс настраиваемый процент (по умолчанию - 50) физической ОЗУ. В зависимости от процента, который вы используете, в большинстве случаев это означает, что процесс не будет убит при попытке использовать уже выделенную память, но при необходимости получит ошибки в распределении памяти.

Ответ 9

Вы можете использовать обертку Tanuki, чтобы создать процесс с помощью POSIX, вместо вилки. http://wrapper.tanukisoftware.com/doc/english/child-exec.html

Функция WrapperManager.exec() является альтернативой Java-Runtime.exec(), которая имеет недостаток в использовании fork (), который может стать на некоторых платформах очень дорогостоящим для создания нового процесса.

Ответ 10

Как ни странно, как это может звучать, одна работа заключается в уменьшении объема памяти, выделенной для JVM. Поскольку fork() дублирует процесс и его память, если вашему процессу JVM не требуется столько памяти, сколько выделено через -Xmx, будет выделено выделение памяти git.

Конечно, вы можете попробовать другие решения, упомянутые здесь (например, перебор или обновление JVM с исправлением). Вы можете попытаться уменьшить память, если отчаянно нуждаетесь в решении, которое сохраняет все программное обеспечение без ущерба для окружающей среды. Также имейте в виду, что уменьшение -Xmx настойчиво может вызвать OOM. Я бы рекомендовал модернизировать JDK как долговременное стабильное решение.

Ответ 11

Простое убийство сработало для меня.

Do

free -m

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

Убейте некоторые задания, которые не требуются.