
Ande Turner
Kann eine Java-Anwendung in einem separaten Prozess unter Verwendung ihres Namens und nicht ihres Speicherorts plattformunabhängig geladen werden?
Ich weiß, dass Sie ein Programm ausführen können über …
Process process = Runtime.getRuntime().exec( COMMAND );
… das Hauptproblem dieser Methode ist, dass solche Aufrufe dann plattformspezifisch sind.
Idealerweise würde ich eine Methode in etwas so Einfaches verpacken wie…
EXECUTE.application( CLASS_TO_BE_EXECUTED );
… und übergeben Sie den vollqualifizierten Namen einer Anwendungsklasse als CLASS_TO_BE_EXECUTED
.

hallidave
Dies ist eine Zusammenfassung einiger der anderen Antworten, die bereitgestellt wurden. Die Java-Systemeigenschaften bieten genügend Informationen, um den Pfad zum Java-Befehl und den Klassenpfad auf eine meiner Meinung nach plattformunabhängige Weise zu ermitteln.
public final class JavaProcess {
private JavaProcess() {}
public static int exec(Class klass, List<String> args) throws IOException,
InterruptedException {
String javaHome = System.getProperty("java.home");
String javaBin = javaHome +
File.separator + "bin" +
File.separator + "java";
String classpath = System.getProperty("java.class.path");
String className = klass.getName();
List<String> command = new LinkedList<String>();
command.add(javaBin);
command.add("-cp");
command.add(classpath);
command.add(className);
if (args != null) {
command.addAll(args);
}
ProcessBuilder builder = new ProcessBuilder(command);
Process process = builder.inheritIO().start();
process.waitFor();
return process.exitValue();
}
}
Sie würden diese Methode wie folgt ausführen:
int status = JavaProcess.exec(MyClass.class, args);
Ich hielt es für sinnvoll, die eigentliche Klasse und nicht die String-Darstellung des Namens zu übergeben, da die Klasse sowieso im Klassenpfad sein muss, damit dies funktioniert.

stepancheg
Zwei Hinweise:
System.getProperty("java.home") + "/bin/java"
gibt Ihnen einen Pfad zur ausführbaren Java-Datei.
((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURL()
hilft Ihnen, den Klassenpfad der aktuellen Anwendung zu rekonstruieren.
Dann deine EXECUTE.application
ist nur (Pseudocode):
Process.exec(javaExecutable, "-classpath", urls.join(":"), CLASS_TO_BE_EXECUTED)

andrej
Wenn Sie die Antwort von @ stepancheg erweitern, würde der tatsächliche Code so aussehen (in Form eines Tests).
import org.junit.Test;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.stream.Collectors;
public class SpinningUpAJvmTest {
@Test
public void shouldRunAJvm() throws Exception {
String classpath = Arrays.stream(((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURLs())
.map(URL::getFile)
.collect(Collectors.joining(File.pathSeparator));
Process process = new ProcessBuilder(
System.getProperty("java.home") + "/bin/java",
"-classpath",
classpath,
MyMainClass.class.getName()
// main class arguments go here
)
.inheritIO()
.start();
int exitCode = process.waitFor();
System.out.println("process stopped with exitCode " + exitCode);
}
}

StaxMan
Das ist vielleicht ein Overkill für Sie, aber Projekt Akuma macht was du willst und mehr. Ich habe es über gefunden dieser Eintrag in Kohsukes (einem der Rock-Start-Programmierer von Sun) fabelhaft nützlichen Blog.
Haben Sie sich die ProcessBuilder-API angesehen? Es ist seit 1.5 verfügbar
http://java.sun.com/javase/6/docs/api/java/lang/ProcessBuilder.html
public abstract class EXECUTE {
private EXECUTE() { /* Procedural Abstract */ }
public static Process application( final String CLASS_TO_BE_EXECUTED ) {
final String EXEC_ARGUMENT
= new StringBuilder().
append( java.lang.System.getProperty( "java.home" ) ).
append( java.io.File.separator ).
append( "bin" ).
append( java.io.File.separator ).
append( "java" ).
append( " " ).
append( new java.io.File( "." ).getAbsolutePath() ).
append( java.io.File.separator ).
append( CLASS_TO_BE_EXECUTED ).
toString();
try {
return Runtime.getRuntime().exec( EXEC_ARGUMENT );
} catch ( final Exception EXCEPTION ) {
System.err.println( EXCEPTION.getStackTrace() );
}
return null;
}
}
Müssen Sie sie wirklich nativ starten? Könnten Sie einfach ihre “Haupt” -Methoden direkt aufrufen? Das einzig Besondere an main ist, dass der VM-Launcher es aufruft, nichts hindert Sie daran, selbst main anzurufen.
.
7845100cookie-checkAusführen einer Java-Anwendung in einem separaten Prozessyes
Wenn ich Sie also richtig verstehe, haben Sie mehrere Klassen mit main()-Methoden und möchten sie in separaten Prozessen starten?
– Michael myers
♦
11. März 09 um 21:32 Uhr
Wie wäre es, wenn Sie exec(“java.exe”, CLASS_TO_BE_EXECUTED.class.getName()) ?
– Michael myers
♦
11. März 09 um 21:49 Uhr
wie man Eingaben von einem Benutzer für eine Java-Klasse entgegennimmt, die ausgeführt wird, wenn ein Prozess von einem Java-Programm gestartet wird, indem etwas wie br.readLine() verwendet wird
– paragjain
15. November 10 um 18:31 Uhr
Ich bin beim OP, es wäre schön, wenn wir die gesamte CLI-Schnittstelle umgehen könnten. Jemand sollte sich wirklich eine Wrapper-Klasse einfallen lassen, damit sich Anwendungsentwickler auf die Geschäftslogik konzentrieren können.
– Sridhar Sarnobat
3. März 15 um 0:11 Uhr