У меня есть коллекция webapps, которые работают под tomcat. Tomcat настроен на 2 ГБ памяти с использованием аргумента -Xmx.
Многие из webapps должны выполнить задачу, которая в конечном итоге использует следующий код:
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(command);
process.waitFor();
...
Проблема, с которой мы сталкиваемся, связана с тем, как этот "дочерний процесс" создается в Linux (Redhat 4.4 и Centos 5.4).
Я понимаю, что объем памяти, равный сумме tomcat, должен быть свободен в пуле физической (не-swap) системной памяти изначально для создания этого дочернего процесса. Когда нам не хватает свободной физической памяти, мы получаем следующее:
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, и сделать ее собственным процессом, с которым Webapp общается как-то. Должны быть и другие.
3) Есть ли еще одна сторона этой проблемы, которую я не вижу, чтобы ее можно было исправить? Уменьшение объема памяти, используемого tomcat, не является вариантом. Увеличение объема памяти на сервере всегда является опцией, но похоже, что это более полоса.
На серверах работает java 6.
EDIT: Я должен указать, что я не ищу специального решения для tomcat. Эту проблему можно увидеть с помощью любого из приложений java, которые мы запускаем на веб-сервере (их несколько). Я просто использовал tomcat в качестве примера, потому что он, скорее всего, будет иметь большую память, выделенную для него, и там, где мы действительно видели ошибку в первый раз. Это воспроизводимая ошибка.
EDIT: в конце концов, мы решили эту проблему, переписав то, что системный вызов выполнял в java. Я чувствую, что нам повезло, что мы можем сделать это без дополнительных системных вызовов. Не все процессы смогут это сделать, поэтому я все равно буду любить видеть фактическое решение этого.