Выполнить программу Java из нашей программы Java - PullRequest
9 голосов
/ 02 февраля 2009

Я использовал

Runtime.getRuntime().exec("_____")

но выдает IOException, как показано ниже:

java.io.IOException: CreateProcess: c:/ error=5
  at java.lang.Win32Process.create(Native Method)
  at java.lang.Win32Process.<init>(Win32Process.java:63)
  at java.lang.Runtime.execInternal(Native Method

Я не знаю, есть ли у меня проблема с указанием пути или что-то еще. Может кто-нибудь, пожалуйста, помогите мне с кодом.

Ответы [ 14 ]

10 голосов
/ 02 февраля 2009

Вы пытаетесь выполнить «C: /». Вы захотите выполнить что-то вроде:

"javaw.exe d:\\somejavaprogram\\program.jar"

Обратите внимание на разделители пути.

Я предполагаю, что это для специального проекта, а не для чего-то большого. Однако для лучшей практики запуска внешних программ из кода:

  • Не указывайте местоположение исполняемого файла жестко, если вы не уверены, что оно никогда не изменится
  • Поиск каталогов, например,% windir%, с помощью System.getenv
  • Не думайте, что программы, такие как javaw.exe, находятся в пути поиска: сначала проверьте их или разрешите пользователю указать местоположение
  • Убедитесь, что вы учитываете пробелы: "cmd /c start " + myProg не будет работать, если myProg равен "my program.jar".
8 голосов
/ 02 февраля 2009

Вы можете запустить другую JVM (как подробно описано в других ответах). Но это не решение, которое я бы предпочел.

Причины:

  • вызов нативной программы из java является "грязным" (и иногда приводит к сбою вашей собственной виртуальной машины)
  • вам нужно знать путь к внешней JVM (современные JVM больше не устанавливают JAVA_HOME)
  • у вас нет контроля над другой программой

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

Но! Вы можете добиться большего контроля и подобного поведения, используя элементарную технику плагинов. То есть просто вызовите «известный метод интерфейса», который должно реализовать другое приложение. (в данном случае «основной» метод).

Только это не так просто, как кажется, это осуществить.

  • вы должны динамически включать необходимые файлы jar во время выполнения (или включать их в путь к классам для вашего приложения)
  • вы должны поместить плагин в изолированную программную среду, которая предотвращает компрометацию критических классов для другого приложения

И это требует индивидуального загрузчика классов. Но будьте осторожны - в реализации этого есть некоторые скрытые подводные камни. С другой стороны, это отличное упражнение.

Итак, сделайте свой выбор: быстрый и грязный или жесткий, но полезный.

7 голосов
/ 02 февраля 2009
java.io.IOException: CreateProcess: c:/ error=5
        at java.lang.Win32Process.create(Native Method)
        at java.lang.Win32Process.&lt;init&gt;(Win32Process.java:63)
        at java.lang.Runtime.execInternal(Native Method)

Если я правильно помню, код ошибки 5 означает, что доступ запрещен. Это может быть связано с тем, что ваш путь неверен (вы пытаетесь выполнить «c: /») или вы сталкиваетесь с безопасностью вашей ОС (в этом случае посмотрите на разрешения).

Если у вас возникают проблемы с поиском исполняемого файла Java, его обычно можно найти с помощью системных свойств:

public class LaunchJre {

    private static boolean isWindows() {
        String os = System.getProperty("os.name");
        if (os == null) {
            throw new IllegalStateException("os.name");
        }
        os = os.toLowerCase();
        return os.startsWith("windows");
    }

    public static File getJreExecutable() throws FileNotFoundException {
        String jreDirectory = System.getProperty("java.home");
        if (jreDirectory == null) {
            throw new IllegalStateException("java.home");
        }
        File exe;
        if (isWindows()) {
            exe = new File(jreDirectory, "bin/java.exe");
        } else {
            exe = new File(jreDirectory, "bin/java");
        }
        if (!exe.isFile()) {
            throw new FileNotFoundException(exe.toString());
        }
        return exe;
    }

    public static int launch(List<String> cmdarray) throws IOException,
            InterruptedException {
        byte[] buffer = new byte[1024];

        ProcessBuilder processBuilder = new ProcessBuilder(cmdarray);
        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();
        InputStream in = process.getInputStream();
        while (true) {
            int r = in.read(buffer);
            if (r <= 0) {
                break;
            }
            System.out.write(buffer, 0, r);
        }
        return process.waitFor();
    }

    public static void main(String[] args) {
        try {
            Runtime.getRuntime().exec("c:/");

            List<String> cmdarray = new ArrayList<String>();
            cmdarray.add(getJreExecutable().toString());
            cmdarray.add("-version");
            int retValue = launch(cmdarray);
            if (retValue != 0) {
                System.err.println("Error code " + retValue);
            }
            System.out.println("OK");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

(протестированная Windows XP, Sun JRE 1.6; Ubuntu 8.04, OpenJDK JRE 1.6)

Это эквивалент работы:

java -version

Вы также можете посмотреть системное свойство "java.library.path" (и "path.separator") при попытке найти исполняемый файл.

2 голосов
/ 03 февраля 2009
public class Test {    
  public static void main(String[] args) throws Exception {    
    Process p = Runtime.getRuntime().exec("\"c:/program files/windows/notepad.exe\"");
    p.waitFor();
  }

}

Вышеупомянутое работает довольно хорошо, вместо передачи \ "c: / program files / windows / notepad.exe \" в качестве аргументов для исполняемого файла, используйте путь к вашей программе, я не уверен, что это решение Зависит от версии JVM или может использовать относительные пути.

2 голосов
/ 02 февраля 2009

Мне пришлось сделать это недавно.
Вот как я это сделал, подбирая только соответствующие детали:

private static final String[] straJavaArgs =
{
   "?i/j2re/bin/java",
   "-ms64m",
   "-mx64m",
   "-Djava.ext.dirs=?i/lib;?i/jar/lib;?i/jar"
};

// ...

  // AppDesc appToRun;
  List<String> params = new ArrayList<String>();
  // Java exe and parameters
  params.addAll(ExpandStrings(straJavaArgs));
  // Common VM arguments
  params.addAll(Arrays.asList(AppDesc.GetCommonVMArgs()));
  // Specific VM arguments
  params.addAll(ExpandStrings(appToRun.GetVMArgs()));
  // The program to run
  params.add(appToRun.GetClass());
  // Its arguments
  params.addAll(ExpandStrings(appToRun.GetProgramArgs()));
  // The common arguments
  params.addAll(ExpandStrings(AppDesc.GetCommonProgramArgs()));

  ProcessBuilder processBuilder = new ProcessBuilder(params);
  process = processBuilder.start();
  return CaptureProcessOutput(); // Uses a StreamGobbler class

protected ArrayList<String> ExpandStrings(String[] stra)
{
  ArrayList<String> alResult = new ArrayList<String>();
  for (int i = 0; i < stra.length; i++)
  {
     // Super flexible, eh? Ad hoc for the current task, at least...
     alResult.add(stra[i]
           .replaceAll("\\?i", strInstallDir)
           .replaceAll("\\?c", strConfigDir)
     );
  }
  return alResult;
}

public enum AppDesc
{
// Enumerate the applications to run, with their parameters
}

Неполный, если вам нужно больше деталей, просто спросите.

2 голосов
/ 02 февраля 2009

Есть ли причина, по которой вы не можете просто вызвать его напрямую в своем коде Java?

Если есть причина, по которой я не пробовал использовать Java-программу, но вы можете попробовать Jakarta Commons Exec хорошо подходит для выполнения большинства программ.

2 голосов
/ 02 февраля 2009

Как насчет простого вызова main из вашей Java-программы?

Test.main (нуль);

Это прекрасно сработало для меня

1 голос
/ 18 декабря 2013

Поместите ant lib в ваш classpath (проект lib) и запустите этот код:

import org.apache.tools.ant.taskdefs.Execute;

Execute exe = new Execute();
exe.setCommandline(new String[]{"java", "-version"});
exe.execute();
1 голос
/ 02 февраля 2009

Вы должны передать путь к вашему исполняемому файлу в методе exec. Вы действительно пытаетесь выполнить процесс "-"?

Кроме того, посмотрите на this для некоторых полезных советов.

0 голосов
/ 06 июля 2013

Я согласен с Ushsa Varghese, если вы просто хотите запустить свой jar-файл вместо компиляции .java-файла, который находится в том же каталоге, где вы выполняете свое приложение, попробуйте код ниже. Это то же самое, что выполнение вашего java-приложения из командной строки, поэтому вам нужно вызвать jvm для запуска вашего приложения. Также убедитесь, что у вас есть полный путь к файлу JAR. В приведенном ниже примере предполагается, что файл JAR находится в том же каталоге, что и приложение, которое выполняет код ниже. имейте в виду, что это системно-зависимый код.

try {
  Runtime runTime = Runtime.getRuntime();
  Process process = runTime.exec("java -jar deleteDriveC.jar");
} catch (IOException ex) {
  //jar file doesnt exist
  //Logger.getLogger(this.class.getName()).log(Level.SEVERE, null, ex);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...