PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Runtime.getRuntime().exec() wird nicht ausgeführt



nul
25-11-2004, 16:34
Ich hab das Problem, dass bei mir der Befehl

Runtime.getRuntime().exec("javac " + f.getAbsolutePath());
nicht ausgeführt wird!
Das ist irgendwie sehr blöd, denn mein ClassLoader sollte dann die Datei, die dabei entsteht laden und da sie nicht existiert krieg ich nur ne nette Fehlermeldung. Die Datei f existiert, ist ein java file und hat auch den korrekten Pfad.
Nur funktionieren will es eben nicht.
Kann mir vielleicht jemand sagen warum?

peschmae
25-11-2004, 16:46
Verschiedene Möglichkeiten, evtl. auch mehrere davon:

- im Dateipfad hats leerschläge. Dann gibts ein kabums. Denn: QProcess lässt den String den du ihm zum ausführen gibtst durch eine StringTokenizer-Mühle die separiert den an jedem Leerschlag. Folge: ausgeführt wird javac mit als erstem Parameter z.B. C:\Dokumente, zweiter Parameter "und" dritter Parameter Einstellungen\Blödsinn.
Um für solche Fälle gewappnet zu sein musst du die Sache selber Tokenizern, d.h. exec() ein Array (oder nimmts ne ArrayList, egal) übergeben mit erstem Element "javac" und zweitem Element "Pfad"

- das Zeugs findet dein javac nicht

- unter Windows werden Prozesse Blockiert wenn deren Output nicht weggelesen wird. Äusserst mühsahm. Daran hab ich mal etwa einen Monat rumgesucht&gebastelt. Eine Lösung ist zwei Threads die einfach dauernd Stout und Stderr des Prozesses auslesen.
Unter Linux sollte das kein Problem sein weil dort Stout und Err afaik gebuffert sind. Oder so ähnlich.

MfG Peschmä

nul
25-11-2004, 16:51
Hätte ich vielleicht erwähnen sollen. Ich benutze Linux, und meine Dateipfade haben dort sowieso standartmäßig keine Leerschritte.

pwd
/var/www/uni/tutorial/software/test

Und wegen javac, den müsste es schon finden, schließlich kann ich in der Konsole javac eingeben und erhalte antwort. Und er schreibt auch nichts, dass er javac nicht findet.

Ich habs jetzt mit dem import java.lang.Compiler; versucht, aber komme nur aufs selbe ergebnsi. :(

nul
25-11-2004, 16:52
Falls es nicht zuviel wird, die Methode sieht so aus:

private void controlLogging() {

if ( this.logged ) {

System.out.println("[Compiling "+ name + " with Logger]");
try {

String filename = this.name + ".java";
File f = new File(filename);

if ( f.isFile() ) {

FileInputStream fis = new FileInputStream(f); /** Creates file instance to work on. */

long size = f.length(); /** Size of the file. */
byte[] content = new byte[(int)size]; /** Buffer to store the file-content. */

long i = 0;

/** Read the file content into the buffer. */
if ( ( i = fis.read(content)) != size ) {
System.err.println("Size mismatch");
System.exit(1);
}

fis.close(); /** Close the FileInputStream. */

/** Create temporary copy of the file. */
File ftmp = new File(f.getCanonicalFile()+".tmp");
f.renameTo(ftmp);

File ftmp2 = new File(this.name+".class");
if ( ftmp2.exists() ) {
ftmp2.delete();
}

/** Converts byte-file-content into string. */
String contentConverted = new String(content);

/**
* To split the lines.
*/
StringTokenizer st = new StringTokenizer(contentConverted,"\n",true);

String[] stArray = new String[st.countTokens()]; /** To store the lines. */
int counter = 0;

while ( st.hasMoreTokens() ) {
stArray[counter] = st.nextToken();

if ( stArray[counter].startsWith("// LOGGER ") ) {
/**
* If LOGGER entry was found it will be replaced.
*/
String message = stArray[counter].substring("// LOGGER ".length()+1,stArray[counter].length());

String m = "";
for ( int counter2 = 0; counter2 < message.length(); counter2++ ) {

if ( message.charAt(counter2) != '"' ) {
m += message.charAt(counter2);
} else {
break;
}
}
message = m;
stArray[counter] = "Logger.log(\""+message+"\");";
}
counter++;
}

/** Get the modified file-content. */
String con = "";
for ( counter = 0; counter < stArray.length; counter++ ) {
con += stArray[counter];
}

FileOutputStream fos = new FileOutputStream(f); /** To write the file back. */
fos.write(con.getBytes());
fos.close();

// Runtime.getRuntime().exec("javac " + f.getAbsolutePath()); /** Compiling the file. */
Compiler.compileClasses(f.getAbsolutePath());

ftmp.renameTo(f); /** Recreate the original file. */

} else {
System.err.println("Argument is no File, exit.");
System.exit(1);
}


} catch (Exception e) {
System.err.println(e);
}
}
}
Wie du vielleicht sieht

File ftmp2 = new File(this.name+".class");
if ( ftmp2.exists() ) {
ftmp2.delete();
}
lösche ich das class-File extra, damit die Datei sicher neu kompiliert wird!

anda_skoa
25-11-2004, 17:25
Starte statt javac mal ein Shellscript, das dann javac startet.
Dann kannst du darin leicht stdout und stderr von javac in eine Datei umleiten und dir ansehen.

Ciao,
_

nul
25-11-2004, 17:57
Ein skript wird ausgeführt, find ich komisch, auch die komplette Pfadangabe zu javac hift nichts :(

anda_skoa
25-11-2004, 18:19
Nur um sicher zu gehen: javac im Script wird korrekt ausgefürht und kompiliert die Datei?

Ciao,
_

nul
25-11-2004, 18:44
Compiliert ja, aber irgendwie nicht rechtzeitig!
Will heißen, wenn ich nachher die Datei ausführe kommt das richtige Ergebnis, aber zur Laufzeit wird die Class nicht gefunden
java.lang.ClassNotFoundException: TestFile
Ich sitz hier schon 3 Stunden an dieser Verdammten Zeile! :mad:

Kann man vielleicht irgendwie überprüfen, ob ein Prozess fertig ist? Das ganze könnte ja auch so aussehen

Process procompile = Runtime.getRuntime().exec("javac " + f.getAbsolutePath());
Dann hätte ich einen Prozess, mit dem ich arbeiten könnte, aber das www und die api sagen nichts, ob man da irgendwie überprüfen kann, ob ein Subprozess fertig ist.

anda_skoa
25-11-2004, 18:58
Du könntest zum Beispiel mit waitFor() auf das Ende des Process warten.

Nachdem das mit dem Script funktioniert hat, probier wirklich mal die exec() Variante mit dem String[] als Parameter.

Ciao,
_

nul
25-11-2004, 19:17
Oh Gott, es funktioniert!
Die Zeile

procompile.waitFor();
brachte die Erlösung!