2009-02-02 22 views
9

ho usatoeseguire un programma Java dal nostro programma Java

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

ma getta una IOException come di seguito:

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 

non so se ho il problema con specificando il percorso o qualcos'altro. Qualcuno può aiutarmi con il codice.

+0

Che cosa significa il getMessage() su tale IOException tornare? –

+1

Vuoi eseguirlo in una VM diversa? Puoi sempre creare un nuovo thread e lasciare che l'altro programma funzioni. –

+0

java.io.IOException: CreateProcess: c:/error = 5 in java.lang.Win32Process.create (metodo nativo) in java.lang.Win32Process. (Win32Process.java:63) in java.lang.Runtime.execInternal (metodo nativo) – Arun

risposta

2

Che ne dici di chiamare il main dal tuo programma java?

Test.main (null);

questo ha funzionato bene per me

+0

Hey amico sta funzionando anche io, ma ho bisogno di usare la classe Runtime. Questo è il grande problema .. – Arun

+1

Perché hai bisogno di runtime se chiamare main() funziona? – Sietse

+5

Chiamare "main" non è senza effetti collaterali. Anche se assicuri che le classi vengano scaricate quando hai finito con loro usando i tuoi caricatori di classe, le applicazioni invocate potrebbero alterare lo stato globale della JVM in modi che sono in conflitto con la tua applicazione. – McDowell

2

C'è qualche motivo non si può semplicemente chiamare direttamente nel codice Java?

Se c'è un motivo per cui non l'ho provato per l'esecuzione di un programma Java, ma si può provare Jakarta Commons Exec funziona bene per l'esecuzione della maggior parte dei programmi.

1

È necessario passare il percorso dell'eseguibile al metodo exec. Stai davvero cercando di eseguire il processo "-"?

Inoltre, dai un'occhiata a this per alcuni suggerimenti utili.

0

Non riesco a ricordare il codice esatto che ho usato per farlo funzionare, ma devi passare "java.exe" (o l'equivalente) come eseguibile e quindi la classe o il jar da eseguire come parametro, con la directory di lavoro corretta. Quindi non è così semplice come chiamare un solo metodo.

10

Si sta tentando di eseguire "C: /". Ti consigliamo di eseguire qualcosa di simile:

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

Avviso i separatori di percorso.

Suppongo che questo sia per un progetto ad-hoc, piuttosto che qualcosa di grande. Tuttavia, per le migliori pratiche in esecuzione di programmi esterni dal codice:

  • Non hardcode la posizione eseguibile, a meno che non si è certi che non cambierà mai
  • Guardi su directory come% windir% utilizzando System.getenv
  • Non supporre che programmi come javaw.exe si trovino nel percorso di ricerca: controlla prima, o consenti all'utente di specificare una posizione
  • Assicurati di prendere in considerazione gli spazi: "cmd /c start " + myProg non funziona se myProg è "my program.jar".
+3

/come separatore di percorso funziona bene in Windows. – PhiLho

+0

Sì, funziona bene per i file semplici, ma è una cattiva abitudine entrare. Cosa succede quando provi ad eseguire una riga di comando, come "cmd/c cd ../myfolder&make" o prova a leggere qualcosa che inizia con "\\? \" ?. Per non parlare della confusione quando l'utente vede "c:/users \ myname/desktop \". – Mark

+0

Le cose si complicano se stai cercando di eseguire 'cmd.exe' da un altro programma. Diventano ancora peggio se si desidera utilizzare 'start' in quanto ha alcune opzioni davvero * strane * ... –

2

Ho dovuto farlo di recente.
Ecco come ho fatto, raccogliendo solo le parti interessate:

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 
} 

incompleta, se avete bisogno di ulteriori dettagli, basta chiedere.

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) 

Se ricordo correttamente, il codice di errore 5 significa accesso negato.Ciò potrebbe essere dovuto al fatto che il tuo percorso non è corretto (cercando di eseguire "c: /") o stai urtando contro la tua sicurezza del sistema operativo (nel qual caso, guarda le autorizzazioni).

Se si hanno problemi a trovare l'eseguibile Java, di solito si può trovare usando le proprietà del sistema:

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(); 
     } 
    } 

} 

(Testato su Windows XP, Sun JRE 1.6, Ubuntu 8.04, OpenJDK JRE 1.6)

Questo è l'equivalente di esecuzione:

java -version 

si consiglia inoltre di guardare la proprietà di sistema "java.library.path" (e "path.separator") quando si cerca di individuare l'executabl e.

7

È possibile avviare un'altra JVM (come descritto in dettaglio in altre risposte). Ma quella non è una soluzione che preferirei.

I motivi sono:

  • chiamando un programma nativo da Java è "sporco" (e, a volte si blocca il proprio VM)
  • è necessario conoscere il percorso della JVM esterna (JVM moderni non lo fanno set JAVA_HOME più)
  • si ha alcun controllo sul l'altro programma

ragione principale per farlo comunque è, che l'altra applicazione non ha alcun controllo sulla tua parte del programma sia. E, cosa più importante, non ci sono problemi con thread di sistema non responsivi come AWT-Thread se l'altra applicazione non conosce la sua threading 101.

Ma! È possibile ottenere un maggiore controllo e un comportamento simile utilizzando una tecnica di plugin elementare. Cioè basta chiamare "un metodo di interfaccia noto" che l'altra applicazione deve implementare. (in questo caso il metodo "principale").

Solo che non è così semplice come sembra.

  • bisogna dinamicamente includere vasi richiesti in fase di esecuzione (o includere nel classpath per la vostra applicazione)
  • devi mettere il plugin in una sandbox che impedisce compromettere le classi fondamentali per l'altra applicazione

E ciò richiede un classloader personalizzato. Ma attenzione: ci sono alcune trappole ben nascoste nella sua implementazione. D'altra parte è un grande esercizio.

Quindi, fate la vostra scelta: o veloce e sporco o duro ma gratificante.

0

Ho avuto un problema simile. Avevo bisogno di eseguire una sezione di codice Java in una VM separata in quanto invocava il codice nativo tramite JNI che occasionalmente faceva esplodere l'intera VM.

Ho barato un po 'però. Inizialmente ho utilizzato Runtime per richiamare un semplice file di comando batch e inserire il comando java work-in-progress. Questo mi ha permesso di modificarlo come necessario e di eseguire il comando in un prompt di DOS per un facile test. Una volta finito, ho semplicemente copiato il risultato nella chiamata di runtime.

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(); 
    } 

} 

I lavori di cui sopra abbastanza bene, invece di passare \ "c:/programmi/windows/notepad.exe \", come gli argomenti per l'eseguibile, usa il percorso del programma, non sono sicuro se questa soluzione è dipendente dalla versione di JVM o se può utilizzare percorsi relativi.

+0

Il codice fornito da jex sopra è pericoloso.Leggi il seguente articolo che lo spiega in maggiori dettagli: http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html Spiega anche come chiamare correttamente il programma nativo esterno dal tuo codice Java . – eneset

0

La risposta è semplice tutto ciò che dovete fare è mettere il codice -

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

Il codice sarebbe simile a questa -

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

Hey penso che questo dovrebbe funzionare. Almeno per me ha funzionato

+0

hmm ... non posso davvero credere che sia possibile eseguire un file _source_ java. Tutto ciò che potrebbe accadere - a seconda della configurazione locale - è che un editor/IDE associato all'estensione del file è acceso :-) – kleopatra

+0

nopes. devi crederci. puoi eseguire un file sorgente java. Cioè puoi ottenere un file di classe. Ma il comando fattoriale $ java non funzionerà. Beh, non l'ho scoperto. Ci possono essere modi che potrebbero essere fatti. –

0

Prima si compila il codice prog-A e si converte in file jar (es .: In NetBeans Shift-F11) e il percorso è di 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"); 

} 
} 
} 

in secondo luogo aprire il nuovo progetto in prog-B e aggiungere le librerie, e selezionare il vaso e dare al file di prog-A.jar e scrivere il due linee nel programma

public class ProgB { 


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

Sono d'accordo con Ushsa Varghese, se vuoi solo eseguire il tuo file jar invece di compilare il file .java che si trova nella stessa direc stai eseguendo la tua applicazione provi il codice qui sotto. È come eseguire l'applicazione java dalla riga di comando, quindi è necessario richiamare jvm per eseguire l'applicazione. Assicurati inoltre di avere il percorso completo del file jar nell'esempio seguente presuppone che il file jar si trovi nella stessa directory dell'applicazione che sta eseguendo il codice sottostante. tieni presente che questo è un codice dipendente dal sistema.

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); 
} 
1

Mettere lib formica in voi classpath (lib progetto) e esegue questo codice:

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

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