У меня есть коллекция веб-приложений, которые работают под tomcat. Tomcat настроен на использование до 2 ГБ памяти с помощью аргумента -Xmx.
Многие из веб-приложений должны выполнить задачу, в результате которой используется следующий код:
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(command);
process.waitFor();
...
Проблема, с которой мы сталкиваемся, связана с тем, как этот «дочерний процесс» создается в Linux (Redhat 4.4 и Centos 5.4).
Насколько я понимаю, объем памяти, равный объему, который использует Tomcat, должен быть изначально свободен в пуле физической (не подкачки) системной памяти для создания этого дочернего процесса. Когда нам не хватает свободной физической памяти, мы получаем это:
java.io.IOException: error=12, Cannot allocate memory
at java.lang.UNIXProcess.<init>(UNIXProcess.java:148)
at java.lang.ProcessImpl.start(ProcessImpl.java:65)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
... 28 more
Мои вопросы:
1) Можно ли убрать требование об объеме памяти, равном свободному родительскому процессу в физической памяти? Я ищу ответ, позволяющий указать, сколько памяти дочерний процесс получает или разрешает Java на Linux получить доступ к памяти подкачки.
2) Каковы альтернативы Runtime.getRuntime (). Exec (), если не существует решения для # 1? Я мог бы думать только о двух, ни один из которых не очень желателен. JNI (очень нежелательно) или переписывание программы, которую мы вызываем на Java, и превращение ее в собственный процесс, с которым веб-приложение каким-то образом общается. Там должны быть другие.
3) Есть ли другая сторона этой проблемы, которую я не вижу, которая потенциально может это исправить? Уменьшение объема памяти, используемой tomcat, не вариант. Увеличение памяти на сервере - это всегда вариант, но похоже, что это просто пластырь.
Серверы работают на Java 6.
РЕДАКТИРОВАТЬ: я должен указать, что я не ищу конкретного кота исправить. Эта проблема может быть замечена с любым из Java-приложений, которые мы запускаем на веб-сервере (их несколько). Я просто использовал tomcat в качестве примера, потому что ему, скорее всего, будет выделено наибольшее количество памяти, и именно там мы впервые увидели ошибку. Это воспроизводимая ошибка.
EDIT: В конце концов, мы решили эту проблему, переписав то, что системный вызов делал в Java. Я чувствую, что нам очень повезло, что мы смогли сделать это без дополнительных системных вызовов. Не все процессы смогут сделать это, поэтому я все равно хотел бы увидеть фактическое решение этого вопроса.