From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001 From: Sven Eisenhauer Date: Fri, 10 Nov 2023 15:11:48 +0100 Subject: add new repo --- .../hjp5/html/k100111.html | 522 +++++++++++++++++++++ 1 file changed, 522 insertions(+) create mode 100644 Master/Reference Architectures and Patterns/hjp5/html/k100111.html (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100111.html') diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100111.html b/Master/Reference Architectures and Patterns/hjp5/html/k100111.html new file mode 100644 index 0000000..e59ae02 --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100111.html @@ -0,0 +1,522 @@ + + + +Handbuch der Java-Programmierung, 5. Auflage + + + + + + + + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage +
 <<  +  <   +  >   + >>  + API  +Kapitel 16 - Utility-Klassen I +
+
+ + + + +

16.4 Die Klasse RunTime

+
+ +
+ + + + +

16.4.1 Grundlagen

+ +

+Die Klasse Runtime +des Pakets java.lang +ermöglicht die Interaktion eines Java-Programms mit dem Bestandteil +seiner Laufzeitumgebung, der dafür verantwortlich ist, Programme +zu starten und zu beenden. Dabei ist es insbesondere möglich, +mit seiner Hilfe externe Programme und Kommandos zu starten, mit ihnen +zu kommunizieren und ihren Zustand zu überwachen. + +

+Objekte der Klasse Runtime +dürfen vom Programm nicht selbst instanziert werden, sondern +werden über die statische Methode getRuntime +der Klasse Runtime +beschafft: +

+ + + + + +
+ +
+public static Runtime getRuntime()
+
+
+
+java.lang.Runtime
+ +

+Um ein externes Programm zu starten, gibt es vier Methoden mit dem +Namen exec: +

+ + + + + +
+ +
+public Process exec(String command)
+  throws IOException
+
+public Process exec(String command, String[] envp)
+  throws IOException
+
+public Process exec(String[] cmdarray)
+  throws IOException
+
+public Process exec(String[] cmdarray, String[] envp)
+  throws IOException
+
+
+
+java.lang.Runtime
+ +

+Das auszuführende Kommando kann wahlweise als Einzelstring angegeben +werden (Kommandoname plus Argumente, getrennt durch Leerzeichen), +oder die einzelnen Bestandteile können in einem Array übergeben +werden. Das optionale zweite Argument envp +ermöglicht es, dem zu startenden Programm eine Liste von Umgebungsvariablen +zu übergeben. + +

+Das folgende Listing zeigt die einfachste Form der Anwendung von exec. +Das Programm startet den notepad-Editor unter Windows: + + +

+ + + + + +
+ +
+001 /* Listing1608.java */
+002 
+003 import java.io.*;
+004 
+005 public class Listing1608
+006 {
+007   public static void main(String[] args)
+008   {
+009     try {
+010       Runtime.getRuntime().exec("notepad");
+011     } catch (Exception e) {
+012       System.err.println(e.toString());
+013     }
+014   }
+015 }
+
+
+Listing1608.java
+ +Listing 16.8: Starten von notepad.exe

+

+ + + + + + + + + +
+ +

+Leider macht die API-Dokumentation keine Angaben darüber, in +welchen Verzeichnissen nach dem auszuführenden Programm gesucht +wird. In den aktuellen Implementierungen des JDK scheint es jedoch +so zu sein, dass alle Verzeichnisse durchsucht werden, die in der +PATH-Umgebungsvariablen angegeben +sind. Unter Windows werden dabei aber offensichtlich nur Dateien mit +den Erweiterungen .com und .exe +automatisch berücksichtigt. Soll dagegen eine .bat-Datei +gestartet werden, muss die Erweiterung .bat +explizit angegeben werden.

+ + + + +
 Hinweis 
+
+ + + + +

16.4.2 Interaktion mit dem externen Programm

+ +

+exec +gibt ein Objekt des Typs Process +zurück, das dazu verwendet werden kann, mit dem gestarteten Programm +zu interagieren. Dazu definiert Process +folgende Methoden: +

+ + + + + +
+ +
+public abstract int waitFor()
+  throws InterruptedException
+
+public abstract int exitValue()
+
+public abstract void destroy()
+
+
+
+java.lang.Process
+ +

+Ein Aufruf von waitFor +terminiert erst, wenn der zugehörige Prozess beendet wurde. Diese +Methode kann also dazu verwendet werden, auf das Ende des gestarteten +Programms zu warten. Das ist beispielsweise sinnvoll, um den Rückgabewert +des Programms auszuwerten oder um mit von ihm erzeugten oder veränderten +Daten zu arbeiten. Wird waitFor +nicht aufgerufen, kann auf aktuellen Betriebssystemen wohl davon ausgegangen +werden, dass das externe Programm parallel zum Java-Programm gestartet +wird und asynchron weiterläuft. Diese Aussage ist allerdings +mit Vorsicht zu genießen, denn spezifiziert ist dieses Verhalten +nicht. Im Zweifel hilft ausprobieren. + +

+Nach Ende des externen Programms kann mit exitValue +sein Rückgabewert abgefragt werden. Dieser gibt bei vielen Programmen +an, ob es fehlerfrei ausgeführt werden konnte oder nicht. Das +ist aber nicht zwangsläufig so. Unter Windows wird insbesondere +beim Aufruf von Batch-Dateien und bei der expliziten Ausführung +eines Kommandos in einen eigenen Kommandointerpreter der Rückgabewert +nicht weitergegeben. In diesem Fall liefert exitValue +immer den Wert 0. Wird exitValue +aufgerufen, wenn der Prozess noch läuft, gibt es eine IllegalThreadStateException. + +

+Die Methode destroy +dient dazu, das externe Programm abzubrechen. Es handelt sich hierbei +nicht um das normale Beenden eines Programms, sondern um einen harten +Abbruch. Ungesicherte Änderungen gehen also verloren und es können +Inkonsistenzen in manipulierten Daten entstehen. + +

+Das Process-Objekt +bietet zusätzlich die Möglichkeit, die Standardein- und +-ausgabe des externen Kommandos umzuleiten und aus dem eigenen Programm +heraus anzusprechen: +

+ + + + + +
+ +
+public OutputStream getOutputStream()
+
+public abstract InputStream getInputStream()
+
+public abstract InputStream getErrorStream()
+
+
+
+java.lang.Process
+ +

+getInputStream +und getErrorStream +liefern einen InputStream, +mit dem die Ausgaben des Prozesses auf Standardausgabe und Standardfehler +gelesen werden können. Von getOutputStream +wird ein OutputStream +zur Verfügung gestellt, mit dem Daten in die Standardeingabe +des Prozesses geschrieben werden können. Auf diese Weise lassen +sich Programme, die über Standardein- und -ausgabe kommunizieren, +fernsteuern bzw. fernabfragen. + +

+Das folgende Programm fasst die wichtigsten Möglichkeiten zusammen: + + +

+ + + + + +
+ +
+001 /* RunCommand.java */
+002 
+003 import java.io.*;
+004 
+005 public class RunCommand
+006 {
+007   static final int MODE_UNCONNECTED = 0;
+008   static final int MODE_WAITFOR     = 1;
+009   static final int MODE_CATCHOUTPUT = 2;
+010 
+011   private static void runCommand(String cmd, int mode)
+012   throws IOException
+013   {
+014     Runtime rt = Runtime.getRuntime();
+015     System.out.println("Running " + cmd);
+016     Process pr = rt.exec(cmd);
+017     if (mode == MODE_WAITFOR) {
+018       System.out.println("waiting for termination");
+019       try {
+020         pr.waitFor();
+021       } catch (InterruptedException e) {
+022       }
+023     } else if (mode == MODE_CATCHOUTPUT) {
+024       System.out.println("catching output");
+025       BufferedReader procout = new BufferedReader(
+026         new InputStreamReader(pr.getInputStream())
+027       );
+028       String line;
+029       while ((line = procout.readLine()) != null) {
+030         System.out.println("  OUT> " + line);
+031       }
+032     }
+033     try {
+034       System.out.println(
+035         "done, return value is " + pr.exitValue()
+036       );
+037     } catch (IllegalThreadStateException e) {
+038       System.out.println(
+039         "ok, process is running asynchronously"
+040       );
+041     }
+042   }
+043 
+044   private static void runShellCommand(String cmd, int mode) 
+045   throws IOException
+046   {
+047     String prefix = "";
+048     String osName = System.getProperty("os.name");
+049     osName = osName.toLowerCase();
+050     if (osName.indexOf("windows") != -1) {
+051       if (osName.indexOf("95") != -1) {
+052         prefix = "command.com /c ";
+053       } else if (osName.indexOf("98") != -1) {
+054         prefix = "command.com /c ";
+055       }
+056     }
+057     if (prefix.length() <= 0) {
+058       System.out.println(
+059         "unknown OS: don\'t know how to invoke shell"
+060       );
+061     } else {
+062       runCommand(prefix + cmd, mode);
+063     }
+064   }
+065 
+066   public static void main(String[] args)
+067   {
+068     try {
+069       if (args.length <= 0) {
+070         System.out.println(
+071           "Usage: java RunCommand [-shell] " +
+072           "[-waitfor|-catchoutput] <command>"
+073         );
+074         System.exit(1);
+075       }
+076       boolean shell = false;
+077       int mode = MODE_UNCONNECTED;
+078       String cmd = "";
+079       for (int i = 0; i < args.length; ++i) {
+080         if (args[i].startsWith("-")) {
+081           if (args[i].equals("-shell")) {
+082             shell = true;
+083           } else if (args[i].equals("-waitfor")) {
+084             mode = MODE_WAITFOR;
+085           } else if (args[i].equals("-catchoutput")) {
+086             mode = MODE_CATCHOUTPUT;
+087           }
+088         } else {
+089           cmd = args[i];
+090         }
+091       }
+092       if (shell) {
+093         runShellCommand(cmd, mode);
+094       } else {
+095         runCommand(cmd, mode);
+096       }
+097     } catch (Exception e) {
+098       System.err.println(e.toString());
+099     }
+100   }
+101 }
+
+
+RunCommand.java
+ +Listing 16.9: Starten externer Programme

+ +

+Das Hauptprogramm erwartet das zu startende Programm und seine Parameter +als Argumente. Wird die Option »-catchoutput« angegeben, +liest das Programm die Ausgaben des gestarteten Programms und gibt +sie auf seiner eigenen Standardausgabe aus. Wird »-waitfor« +angegeben, wartet das Programm auf das Ende des gestarteten Programms, +ohne dessen Ausgaben anzuzeigen. In beiden Fällen wird schließlich +der Rückgabewert des Programms ausgegeben. Durch Angabe der Option +»-shell« kann das externe Programm mit einem separaten Kommandointerpreter +gestartet werden. Das ist beispielsweise nützlich, um Shell-Kommandos +auszuführen, die nicht als eigenständige Programmdateien +existieren. + +

+Der folgende Aufruf verwendet das Beispielprogramm, um das interne +MS-DOS-Kommando »set« auszuführen (es gibt die Inhalte +aller Umgebungsvariablen aus): + +

+java RunCommand -shell -catchoutput set
+
+ + +

+Seine Ausgabe könnte etwa so aussehen: + +

+Running command.com /c set
+catching output
+  OUT> winbootdir=C:\WINDOWS
+  OUT> COMSPEC=C:\COMMAND.COM
+  OUT> TEMP=C:\tmp
+  OUT> TMP=c:\tmp
+  OUT> USER=guido
+  OUT> windir=C:\WINDOWS
+  OUT> PATH=C:\JDK1.6\BIN;C:\WINDOWS;C:\WINDOWS\COMMAND;
+  OUT> CLASSPATH=.;c:\arc\prog\java
+  OUT> PROMPT=$p--$g
+done, return value is 0
+
+ +

+ + + + + + + + + +
+ +

+Die Übergabe des Programms an einen separaten Kommandointerpreter +erfolgt in der Methode runShellCommand +ab Zeile 044. Wie ein derartiger +Aufruf ausgeführt wird, ist natürlich betriebssystem- und +konfigurationsabhängig. Das Beispielprogramm versucht, einige +brauchbare Varianten für gängige Betriebssysteme vorzudefinieren. +Weitere können leicht hinzugefügt werden.

+ + + + +
 Hinweis 
+
+

+ + + + + + + + + + + +
+ +

+Während des Tests von RunCommand +gab es mitunter Schwierigkeiten beim Ausführen interner DOS-Programme +unter Windows 95 und 98. Während sich beispielsweise das Kommando +set problemlos aufrufen ließ, +gab es beim Aufruf von dir Hänger, +nach denen die MS-DOS-Task hart abgebrochen werden mußte. Die +JDK Bug Database listet eine ganze Reihe von Problemen in Zusammenhang +mit dem Aufruf von 16-Bit-Programmen unter Windows 95 oder 98 auf. +Sie rühren unter anderem daher, dass die Ein- und Ausgabepuffer +der DOS-Programme so klein sind, dass die Programme mitunter schon +blockieren, bevor die aufrufende Applikation die Chance hatte, eine +Verbindung zu ihnen herzustellen. Echte Workarounds für diese +Probleme scheinen nicht bekannt zu sein. Beim Aufruf von 32-Bit-Programmen +treten die Probleme offenbar nicht auf.

+ + + + +
 Warnung 
+
+


+ + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 +
 <<  +  <   +  >   + >>  + API  +© 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de +
+ + + -- cgit v1.2.3