Ausführen einer Java-Anwendung in einem separaten Prozess

Lesezeit: 5 Minuten

Ausfuhren einer Java Anwendung in einem separaten Prozess
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.

  • 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

Ausfuhren einer Java Anwendung in einem separaten Prozess
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.

  • Möglicherweise müssen Sie verwenden redirectOutput(...) und redirectError(...) auf dem Process Builder (vorher start()), wenn Sie einen Server starten möchten, da dieser sonst möglicherweise hängen bleibt und Sie ihn möglicherweise nicht kontaktieren können. Bin mir aber nicht sicher warum…

    – nyg

    12. April 16 um 11:47 Uhr

  • Wie der neue Prozess im getrennten Modus ausgeführt wird, damit der äußere Prozess seine Arbeit fortsetzen kann

    – Tagträumer

    5. Juni 16 um 0:20 Uhr

  • Danke! Das Trennen von “-cp” vom eigentlichen Klassenpfad hat geholfen. Wenn sie zu einem einzigen String zusammengefügt werden, wird “Unrecognized option: -cp ” ausgegeben.

    – asg

    25. Oktober 16 um 11:29 Uhr

  • Es könnte besser sein, es zu verwenden String className = klass.getName(); anstatt String className = klass.getCanonicalName(); um verschachtelte Klassen richtig zu handhaben.

    – John29

    19. November 18 um 21:22 Uhr

  • Kennt jemand die Technik zum Einfügen von VM-Argumenten, dh -D und -X für ProcessBuilder? Ich habe die Anweisungen im API-Dokument befolgt, um processbuilder.environment() zu verwenden, um eine Karte anzuzeigen, aber die Werte scheinen im aufgerufenen Programm nicht verfügbar zu sein – dh System.getProperty(“xyz”, value) ist nicht verfügbar im aufgerufenen Programm, obwohl ich sehe, dass es richtig gesetzt ist

    – robbie70

    9. April 19 um 17:34 Uhr


Ausfuhren einer Java Anwendung in einem separaten Prozess
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)

  • Dritter Hinweis: Verwenden Sie urls.join(“:”) nicht, wenn Sie plattformunabhängig sein möchten.

    – jdigital

    12. März 09 um 3:58 Uhr

  • File.some_constant statt : (Sie können some_constant nachschlagen 🙂

    – TofuBier

    13. März 09 um 14:50 Uhr

  • Der URL-Ansatz gibt mir die URL zur JAR-Datei aus der Codebasis der JNLP-Datei. dh url.com/Jar.jar. Das funktioniert bei mir nicht. Während es lokal war, tat es das.

    – javydreamercsw

    18. April 13 um 21:28 Uhr

  • @ Jean docs.oracle.com/javase/1.5.0/docs/api/java/io/…

    – NaXa

    11. September 14 um 14:09 Uhr

  • Bitte korrigieren Sie den “Pseudocode”: Es ist äußerst schwierig, syntaktisch korrekt zu werden, wenn Sie mit diesen Klassen nicht vertraut sind.

    – Benutzer508402

    20. November 14 um 19:42 Uhr

1644073088 40 Ausfuhren einer Java Anwendung in einem separaten Prozess
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);
    }
}

1644073088 54 Ausfuhren einer Java Anwendung in einem separaten Prozess
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.

.

784510cookie-checkAusführen einer Java-Anwendung in einem separaten Prozess

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy