从我们的Java程序执行Java程序

时间:2009-02-02 08:06:30

标签: java

我用过

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 个答案:

答案 0 :(得分:10)

您正在尝试执行“C:/”。你想要执行类似的东西:

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

注意路径分隔符。

我假设这是一个特别的项目,而不是一个大的项目。但是,有关从代码运行外部程序的最佳实践:

  • 不要对可执行位置进行硬编码,除非您确定它永远不会改变
  • 使用System.getenv
  • 查找%windir%等目录
  • 不要假设像javaw.exe这样的程序在搜索路径中:先检查它们,或允许用户指定位置
  • 请确保考虑空格:如果myProg为"cmd /c start " + myProg"my program.jar"将无效。

答案 1 :(得分:8)

您可以启动另一个JVM(如其他答案中详细描述的)。 但这不是我想要的解决方案。

原因是:

  • 从java调用本机程序是“脏的”(有时会崩溃你自己的VM)
  • 您需要知道外部JVM的路径(现代JVM不再设置JAVA_HOME)
  • 您无法控制其他程序

无论如何,这样做的主要原因是,另一个应用程序也无法控制您的部分程序。更重要的是,如果其他应用程序不知道其线程101,那么像AWT-Thread这样的无响应系统线程也没有问题。

但是!通过使用基本插件技术,您可以实现更多控制和类似行为。即只需调用另一个应用程序必须实现的“已知接口方法”。 (在这种情况下是“主要”方法)。

只有它听起来并不像听起来那么简单。

  • 您必须在运行时动态包含所需的jar(或将它们包含在应用程序的类路径中)
  • 您必须将插件放在沙箱中,以防止将关键类泄露给其他应用程序

这需要一个自定义的类加载器。但要注意 - 实施这一点有一些隐藏的陷阱。另一方面,这是一个很好的练习。

所以,请选择:快速,肮脏或艰难但有益。

答案 2 :(得分:7)

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”)。

答案 3 :(得分:2)

如何从java程序中调用main?

Test.main(空);

这对我来说很好用

答案 4 :(得分:2)

有什么理由不能直接在Java代码中调用它吗?

如果我没有尝试过执行Java程序的原因,你可以试试Jakarta Commons Exec可以很好地执行大多数程序。

答案 5 :(得分:2)

我最近不得不这样做 我是这样做的,只选择相关部分:

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
}

不完整,如果您需要更多详细信息,请询问。

答案 6 :(得分:2)

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版本,或者它是否可以使用相对路径。

答案 7 :(得分:1)

您必须在exec方法中传递可执行文件的路径。你真的想要执行“ - ”过程吗?

另外,请查看this以获取一些有用的提示。

答案 8 :(得分:1)

将ant lib放在classpath(项目库)中并运行以下代码:

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

Execute exe = new Execute();
exe.setCommandline(new String[]{"java", "-version"});
exe.execute();

答案 9 :(得分:0)

我记不清用于使其工作的确切代码,但您必须将“java.exe”(或等效的)作为可执行文件传递,然后将类或jar作为参数运行,使用正确的工作目录。所以它并不像调用一个方法那么简单。

答案 10 :(得分:0)

我有一个类似的问题。我需要在一个单独的VM中运行一段Java代码,因为它通过JNI调用本机代码,偶尔会导致整个VM崩溃。

我虽然骗了一点。我最初使用Runtime来调用一个简单的批处理命令文件,并将work-in-progress java命令放在那里。这使我能够根据需要进行调整,并在DOS提示符下运行该命令以便于测试。完成后,我只是将结果复制到Runtime调用中。

答案 11 :(得分:0)

答案很简单,你所要做的就是把代码 -

$ process p = Runtime.getRuntime().exec("javac factorial.java"); in the try catch block

代码看起来像这样 -

try
{
process p = Runtime.getRuntime().exec("javac factorial.java");
}
catch(IOException e)
{
e.printStackTrace();
}

嘿,我认为这应该有效。至少对我来说它确实有效

答案 12 :(得分:0)

首先编译prog-A代码并转换为jar文件(即:在NetBeans Shift-F11中),路径是netbeans(NetBeansProjects / prog-A / dist / prog-A.jar)

 public class ProgA {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    System.out.println("Helllo print thr ProgA");

}
}
}

第二步在prog-B中打开新项目并添加库,选择jar并输入prog-A.jar文件并在程序中写下两行

public class ProgB {


public static void main(String[] args) {
    ProgA progA = new  ProgA();
    String arg[] = null;
    progA.main(arg);
}
}

答案 13 :(得分:0)

我同意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);
}