LINUX.ORG.RU

[Java] запуск внешней программы

 


0

0

Уважаемые форумчане! Написал свою программу (С/С++), которая в своих итерационных расчетах использует внешнюю программу ngspice. Так как расчет итерационный, то ngspice вызывается огромное количество раз. При запуске моей проги из консоли — все ОК, т. е. все что мне надо и сколько надо (по времени и количеству вызовов внешней программы).

Так запускаю NGSPICE в C++:

string exec=spice_path+" -b "+tmpspicein+" > "+tmpspiceout; sys_res=system(exec.c_str());

Далее. Для этой моей программки написал GUI на Java, где теперь моя консольная программа вызывается как внешняя:

Так запускаю свою прогу из Java:

proc = Runtime.getRuntime().exec("./SpiceExtr"+" "+Alg);

Проблема заключается в том, что после некоторого количества вызовов программы ngspice моя консольная программы доходит до строчки sys_res=system(exec.c_str()); и дальше просто перестает работать. Процесс (ngspice) есть, но он не считает (типа висит). Если запустить с теми же наптройками мою программу из консоли, то все работает, а если из GUI — то спустя какое-то количество вызовов программы ngspice — подвисает.

Резюме (для обобщения)

1______________2_________________________3

мой GUI → моя консольная программа → ngspice.

2→3 — OK

1→2→3 — не ОК.

Причем, зависание происходит примерно после тысячного запуска программы ngspice.

Может в java какие то ограничения есть для запуска внешних программ? Там, по памяти или что еще? При подвисании система работает нормально, а процесс ngspice потребряет 0% CPU.

Куда копать?

Там есть неожиданный кариес с этим Runtime.getRuntime().exec(), т.к надо выфетчивать весь stdout и stderr у внешнего процесса, иначе он засрет весь буффер и повиснет. JVM никакой неявной автоматизации тут не делает в отличие о шелла или перла. Вот в этой книге (*) приведен полноценный враппер для Runtime.getRuntime().exec(), который обходит все подводные камни в IPC.

(*) http://www.amazon.com/Java-Pitfalls-Time-Saving-Solutions-Workarounds/dp/0471...

Absurd ★★★
()
Ответ на: комментарий от Absurd

Спасибо, теперь хоть известно куда копать.

От дополнительной инфы пока не отказываюсь))

spike_by
() автор топика

М.б., подумать о JNI ?

ef37 ★★
()

Не слишком ли делать обёртку для консольной программы на Java? Есть же биндинги у того же перла к GTK, питон в конце концов ?

roy ★★★★★
()

public void run(){

String s = null;

String se = null;

String so = null;

try{

jB.setText("Stop");

proc = Runtime.getRuntime().exec("./SpiceExtr"+" "+Alg);

System.out.println("Run: ./SpiceExtr"+" "+Alg);

te = new TextEditor();

te.go().setTitle("Output");

te.go().setVisible(true);

te.setColor(Color.lightGray);

/*InputStream is = proc.getInputStream();

InputStreamReader isr = new InputStreamReader(is);

BufferedReader br = new BufferedReader(isr);*/

BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));

BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

OutputStream stdOut = new BufferedOutputStream( proc.getOutputStream());

//BufferedReader stdOutput = new BufferedReader(new OutputStream(proc.getOutputStream()));

//read the output from the command

while (((s = stdInput.readLine()) != null)&&((se = stdError.readLine()) != null)) {

System.out.println(s);

System.out.println(se);//перенаправляй здесь

stdOut.toString();

te.addline(s+newline);

}

int exitVal = proc.waitFor();

System.out.println("exitValue: "+exitVal);

jB.setText("Run");

}catch (IOException e) {

e.printStackTrace();

System.out.println("Viewing Faild");

}catch (Exception err) {

err.printStackTrace();

}/*catch (Throwable t){

t.printStackTrace();

}*/

}

заменил код работы с буффером (закомментированный - старый вариант) стал считвть в 2 раза дольше. Капкой из буферов надо еще учитывать. (Книгу пока не нашелб ищу))))

spike_by
() автор топика
Ответ на: комментарий от roy

да мне надо быдл быстро накидать GUI. perl+GTK - не знаюю Делал на чем умею.

spike_by
() автор топика
Ответ на: комментарий от spike_by

Ну вообще я думаю что надо читать из stdout и stderr дочерней программы. В stdin надо *писать* если есть такая необходимость.

Absurd ★★★
()
Ответ на: комментарий от spike_by

>Капкой из буферов надо еще учитывать. (Книгу пока не нашелб ищу))))

Посмотри исходники ant если нет книги - этот аналог make для жабы по долгу службы вызывает кучу консольных утилит.

Absurd ★★★
()
Ответ на: комментарий от spike_by

>а неужели нету готового класса, который эту проблему разруливал бы?)

org/apache/tools/ant/taskdefs/Exec.java

Нашел грепанием "Runtime" в *.java исходниках анта. Первое же вхождение.

Absurd ★★★
()
Ответ на: комментарий от Absurd

Спасибо за помощь! Вроде разобрался и все заработало!

spike_by
() автор топика

Есть еще способ запуска внешней программы - ProcessBuilder.

vorpal
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.