Этот ответ задерживается, но у нас та же проблема, и проблема для нас заключается в том, как Solaris управляет памятью.
Проблема в том, что когда у нас есть сервер приложений, использующий в моем случае большой объем памяти 10 ГБ, и мы хотим запустить простое «ls», для запуска нового процесса требуется 10 ГБ.
Солярису требуются дополнительные 10 ГБ, доступные на нашем сервере, в Linux используется функция, известная как «копирование при записи». Эта функция уменьшает накладные расходы на создание нового процесса
http://developers.sun.com/solaris/articles/subprocess/subprocess.html
Историческая справка и описание проблемы
Традиционно в Unix был только один способ создания нового процесса: использование системного вызова fork (), за которым часто следует системный вызов exec (). Вызов fork () создает копию адресного пространства всего родительского процесса, а exec () превращает эту копию в новый процесс.
(Примечание. В ОС Solaris термин пространство подкачки используется для описания комбинации физической памяти и дискового пространства подкачки, настроенных для системы. Однако в других системах Unix этот термин может означать пространство подкачки на диске, также известное в качестве резервного хранилища. Чтобы избежать путаницы, я буду использовать термин «виртуальная память» (VM) для обозначения физической памяти и дискового пространства.)
Обычно метод fork / exec работал достаточно хорошо. Однако в некоторых случаях он имеет недостатки, такие как нехватка памяти без уважительной причины и низкая производительность разветвления.
Недостаточно памяти: для процесса с большой памятью системный вызов fork () может завершиться ошибкой из-за недостаточного количества виртуальных машин, поскольку fork () требует вдвое больше родительской памяти. Это может произойти, даже если после fork () сразу же следует вызов exec (), который освободит большую часть этой дополнительной памяти. Когда это происходит, приложение обычно завершает работу.
Например, предположим, что 64-разрядное приложение в данный момент потребляет 6 гигабайт (Гбайт) виртуальной машины, и ему необходимо создать подпроцесс для запуска команды ls (1). Родительский процесс выдает вызов fork (), который завершится успешно только в том случае, если на данный момент доступно еще 6 ГБ виртуальной машины. Если в системе недостаточно доступной виртуальной машины (что часто встречается), fork () завершится с ошибкой ENOMEM. Очевидно, что команде ls (1) не нужно где-то около 6 Гбайт памяти для запуска, но fork () этого не знает.
Та же проблема может возникнуть не только в приложениях, но и в собственных инструментах Sun. Например, для dbx была подана следующая Sun RFE (запрос на улучшение): «Оболочка 4748951 dbx должна использовать posix_spawn () для не встроенных команд, а не для fork (2)».
RFE 4748951 появился, когда утилита клиента вызвала dbx для чтения огромного файла ядра, используя скрипт, который также должен был выполнить команду cut (1) из dbx. Они получили сообщение не может - попробуйте еще раз сообщение об ошибке, приводящее к прерыванию dbx. Расследование показало, что dbx использовал fork / exec для выполнения этой крошечной команды cut (1) и исчерпал ВМ во время вызова fork ().
Виртуальная машина Java Solaris (JVM) также страдает от той же проблемы в настоящее время, как описано в этом Sun RFE: "5049299 Используйте posix_spawn, а не fork, на S10, чтобы избежать исчерпания подкачки".
Итак, у вас есть 3 варианта.
1.- Выполнить функцию Runtime.exec ранее.
2.- Создайте межпроцессное взаимодействие с другим сервером Java и выполните команду Runtime.exec.
3.- Создайте класс JNI для вызова системной функции C. Я беру этот вариант, и он отлично работает.
Я положил здесь свой пример кода.
Java-код.
public class CallOS {
static {
System.loadLibrary("CallOS");
}
public native int exec(java.lang.String cmd);
public static void main(String[] args) {
int returnValue = 0;
returnValue = new CallOS().exec("ls -la");
System.out.println("- " + returnValue);
}
}
Код заголовка C. Это генерируется с помощью javah -jni CallOS
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class CallOS */
#ifndef _Included_CallOS
#define _Included_CallOS
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: CallOS
* Method: exec
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_CallOS_exec
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
C-код.
#include "CallOS.h"
#include <stdlib.h>
JNIEXPORT jint JNICALL Java_CallOS_exec
(JNIEnv *env, jobject obj, jstring cmd)
{
jint retval;
jbyte *str;
str = (*env)->GetStringUTFChars(env, cmd, NULL);
if(str == NULL) return NULL;
retval = system(str);
(*env)->ReleaseStringUTFChars(env, cmd, str);
return retval;
};
Надеюсь, это поможет вам.