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/k100110.html | 817 +++++++++++++++++++++ 1 file changed, 817 insertions(+) create mode 100644 Master/Reference Architectures and Patterns/hjp5/html/k100110.html (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100110.html') diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100110.html b/Master/Reference Architectures and Patterns/hjp5/html/k100110.html new file mode 100644 index 0000000..d0be778 --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100110.html @@ -0,0 +1,817 @@ + + + +Handbuch der Java-Programmierung, 5. Auflage + + + + + + + + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage +
 <<  +  <   +  >   + >>  + API  +Kapitel 16 - Utility-Klassen I +
+
+ + + + +

16.3 Die Klasse System

+
+ +
+ +

+Neben den bisher vorgestellten Datenstrukturen des Pakets java.util +gibt es in java.lang +eine Klasse System, +die eine Reihe nützlicher Hilfsmittel zur Verfügung stellt. +Die wichtigsten von ihnen sollen in den folgenden Abschnitten besprochen +werden. + + + + +

16.3.1 System-Properties

+ +

+In Java gibt es keine Möglichkeit, direkt auf die Umgebungsvariablen +eines Programms zuzugreifen. Ein solcher Zugriff wurde von den Java-Designern +als nichtportabel angesehen und statt dessen durch das Konzept der +Properties ersetzt. Properties sind Listen von Eigenschaften, +die dem Programm vom Java-Laufzeitsystem zur Verfügung gestellt +werden. Jede Eigenschaft besitzt einen Namen, unter dem auf sie zugegriffen +werden kann. Das Java-Laufzeitsystem stellt standardmäßig +die folgenden Properties zur Verfügung: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyBedeutung
java.versionJava-Versionsnummer
java.vendorHerstellerspezifische Zeichenkette
java.vendor.urlURL (also ein Internet-Link) zum Hersteller +
java.homeInstallationsverzeichnis
java.class.versionVersionsnummer der Java-Klassenbibliothek +
java.class.pathAktueller Klassenpfad
os.nameName des Betriebssystems
os.archBetriebssystem-Architektur
os.versionVersionsnummer des Betriebssystems
file.separatorTrennzeichen für die Bestandteile eines +Pfadnamens
path.separatorTrennzeichen für die Laufwerksangabe +eines Pfadnamens
line.separatorZeichenkette für Zeilenschaltung
user.nameName des angemeldeten Benutzers
user.homeHome-Verzeichnis
user.dirAktuelles Arbeitsverzeichnis
java.vm.specification.versionVersion der VM-Spezifikation
java.vm.specification.vendorHersteller der VM-Spezifikation
java.vm.specification.nameBezeichnung der VM-Spezifikation
java.vm.versionVM-Version
java.vm.vendorHersteller der VM
java.vm.nameName der VM-Implementierung
java.specification.versionVersion der Spezifikation der Laufzeitumgebung +
java.specification.vendorHersteller der Spezifikation der Laufzeitumgebung +
java.specification.nameBezeichnung der Spezifikation der Laufzeitumgebung +
+

+Tabelle 16.2: Standard-Properties

+ +

+Für den Zugriff auf diese Eigenschaften steht die Klasse Properties +aus dem Paket java.util +zur Verfügung. Sie bietet die Möglichkeit, Property-Listen +zu erzeugen, mit Werten zu füllen und vorhandene Werte auszulesen. +Die Klasse Properties +ist eine Ableitung der Klasse Hashtable +und stellt damit eine Tabelle von Schlüssel-/Wertepaaren dar. + +

+Für den Zugriff auf einzelne Properties reicht meist die einfach +zu bedienende Klassenmethode getProperty +der Klasse System +in java.lang +aus: +

+ + + + + +
+ +
+public static String getProperty(String key)
+public static String getProperty(String key, String default)
+
+
+
+java.lang.System
+ +

+Die erste Variante liefert die Eigenschaft mit dem Namen key +in Form einer Zeichenkette. Falls keine Eigenschaft mit diesem Namen +gefunden wurde, wird null +zurückgegeben. Die zweite Variante erlaubt die Übergabe +eines Standardwertes. Der Unterschied zur ersten Variante besteht +darin, dass nicht null, +sondern der Standardwert zurückgegeben wird, wenn die gesuchte +Eigenschaft nicht gefunden wurde. + +

+Die Methode getProperties +liefert das komplette Properties-Objekt +mit den System-Properties: +

+ + + + + +
+ +
+public static Properties getProperties()
+
+
+
+java.lang.System
+ +

+Das folgende Programm gibt eine Liste aller System-Properties auf +dem Bildschirm aus. Es verwendet dazu zunächst die Methode getProperties, +um das System-Properties-Objekt +zu beschaffen. Anschließend erzeugt es durch Aufruf von propertyNames +einen Enumerator, mit dem alle Schlüsselwerte durchlaufen werden +können und mit dem durch Aufruf von getProperty +der zugehörige Wert ermittelt werden kann. Auf diese Weise listet +das Programm alle verfügbaren System-Properties auf (das sind +in der Regel sehr viel mehr als die plattformübergreifend spezifizierten): + + +

+ + + + + +
+ +
+001 /* Listing1604.java */
+002 
+003 import java.util.*;
+004 
+005 public class Listing1604
+006 {
+007   public static void main(String[] args)
+008   {
+009     Properties sysprops   = System.getProperties();
+010     Enumeration propnames = sysprops.propertyNames();
+011     while (propnames.hasMoreElements()) {
+012       String propname = (String)propnames.nextElement();
+013       System.out.println(
+014         propname + "=" + System.getProperty(propname)
+015       );
+016     }
+017   }
+018 }
+
+
+Listing1604.java
+ +Listing 16.4: Ausgeben der System-Properties

+ + + + +

16.3.2 in, err und out

+ +

+In den vorangegangenen Kapiteln wurde schon häufig der Aufruf +System.out.println +verwendet, um Daten auf die Standardausgabe bzw. in ein Debug-Fenster +auszugeben. Diese Anweisung ruft die Methode println +des Objekts out +der Klasse System +auf. Dabei ist out +eine statische Variable vom Typ PrintStream, +die beim Starten des Programms so initialisiert wird, dass ihre Ausgabe +auf die Standardausgabe geleitet wird. + +

+Analog zu out +gibt es die statischen Variablen err +und in. +Dabei dient err +zur Ausgabe von Fehlermeldungen, und in +ist ein Standardeingabekanal, der dazu verwendet werden kann, Eingaben +von der Tastatur zu lesen. + +

+Mit Hilfe der Methoden setIn, +setOut +und setErr +ist es sogar möglich, die Standardein- und -ausgabe aus dem Programm +heraus umzuleiten: +

+ + + + + +
+ +
+public static void setIn(InputStream in)
+
+public static void setOut(PrintStream out)
+
+public static void setErr(PrintStream err)
+
+
+
+java.lang.System
+

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

+Die Verwendung dieser Klassenvariablen ist im Grunde genommen nicht +konform mit dem Dialogkonzept einer GUI-Anwendung. Ihr Einsatz kann +aber immer dann sinnvoll sein, wenn Java-Programme geschrieben werden +sollen, die keine ausgefeilte Oberfläche benötigen. In diesem +Fall sind sie ein nützliches Hilfsmittel, um einfache Ein-/Ausgaben +ohne großen Aufwand realisieren zu können. Bereits in Kapitel 3 +wurde gezeigt, wie man diese Routinen zur Ein- und Ausgabe verwenden +kann. Weitere Informationen darüber sind in Kapitel 19 +zu finden, das sich mit Byte-Streams beschäftigt.

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

16.3.3 exit

+ +

+Auch Aufrufe der Methode System.exit +sind uns schon begegnet: +

+ + + + + +
+ +
+public static void exit(int status)
+
+
+
+java.lang.System
+ +

+Mit System.exit +wird das laufende Programm beendet. Der Aufrufparameter status +dient als Fehleranzeige und wird als Exitcode an den Aufrufer des +Programms zurückgegeben. Gemäß Konvention zeigt dabei +ein Wert größer oder gleich 1 einen Fehler während +der Programmausführung an, während 0 ein fehlerfreies Programmende +signalisiert. +

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

+Neben der Methoden System.exit +bietet die weiter unten beschriebene Klasse Runtime +auch die Methode System.halt +an, bei der die Virtuelle Machine sofort angehalten wird. Im Unterschied +zu Runtime.halt werden dabei +weder finalize -Methoden noch +finally-Zweige abgearbeitet. +Dies kann - z.B. beim Zugriff auf eine Datenbank - dazu führen, +dass externe Ressourcen nicht zurückgegeben werden. Sie sollten +deshalb auf die Verwendung von Runtime.halt +verzichten.

+ + + + +
 Warnung 
+
+ + + + +

16.3.4 gc

+

+ + + + + +
+ +
+public static void gc()
+
+
+
+java.lang.System
+ +

+Ein Aufruf der Methode gc +führt einen expliziten Aufruf des Garbage Collectors +durch. Dieser sucht dann nach freiem Speicher und gibt diesen an das +Laufzeitsystem zurück. Normalerweise ist ein Aufruf dieser Methode +nicht erforderlich, denn der Garbage Collector läuft ständig +als niedrig priorisierter Thread im Hintergrund. Der Aufruf von gc +ist immer dann sinnvoll, wenn eine explizite Kontrolle über den +Zeitpunkt der Speicherfreigabe gewünscht ist. + + + + +

16.3.5 currentTimeMillis

+ +

+Die Methode currentTimeMillis +liefert die Anzahl der Millisekunden, die zum Zeitpunkt des Aufrufs +seit Mitternacht des 1.1.1970 vergangen sind: +

+ + + + + +
+ +
+public static long currentTimeMillis()
+
+
+
+java.lang.System
+

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

+Ob dabei tatsächlich eine Auflösung von einer Millisekunde +erreicht wird, ist von der konkreten Java-Implementierung abhängig. +In PC-basierten Java-Systemen orientiert sie sich meist an der Auflösung +des System-Timers. Dieser wird 18,2 mal pro Sekunde aufgerufen, so +dass die Auflösung damit bei etwa 55 ms. liegt.

+ + + + +
 Hinweis 
+
+ +

+Mit dem folgenden Beispielprogramm kann die Auflösung des System-Timers +ermittelt werden: + + +

+ + + + + +
+ +
+001 /* Listing1605.java */
+002 
+003 public class Listing1605
+004 {
+005   public static void main(String[] args)
+006   {
+007     long t1, t2;
+008     int  actres, sumres = 0, i = 0;
+009     while (true) {
+010       ++i;
+011       t1 = System.currentTimeMillis();
+012       while (true) {
+013         t2 = System.currentTimeMillis();
+014         if (t2 != t1) {
+015           actres = (int)(t2 - t1);
+016           break;
+017         }
+018       }
+019       sumres += actres;
+020       System.out.print("it="+i+", ");
+021       System.out.print("actres="+actres+" msec., ");
+022       System.out.print("avgres="+(sumres/i)+" msec.");
+023       System.out.println("");
+024       try {
+025         Thread.sleep(500);
+026       } catch (InterruptedException e) {
+027         //nichts
+028       }
+029     }
+030   }
+031 }
+
+
+Listing1605.java
+ +Listing 16.5: Die Auflösung des System-Timers bestimmen

+ +

+Das Programm bestimmt zunächst die aktuelle Systemzeit und merkt +sich den Wert in der Variablen t1. +Nun wird die Systemzeit in einer Schleife erneut so oft gemessen, +bis sie sich geändert hat. Die Differenz zwischen beiden Werten +wird als Auflösung des aktuellen Durchgangs angesehen und der +Variablen actres zugewiesen. +

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

+Um eine größere Genauigkeit zu erzielen, führt das +Programm die Bestimmung der Auflösung mit Hilfe der äußeren +Schleife viele Male durch. Die dabei jeweils ermittelte Auflösung +wird in der Variablen sumres +addiert und durch Division durch die Anzahl der Schleifendurchläufe +zur Ermittlung des gleitenden Durchschnitts verwendet. Das so errechnete +Ergebnis pendelt sich tatsächlich bereits nach wenigen Durchläufen +auf den vorausgesagten Wert von 55 ms. ein:

+ + + + +
 Hinweis 
+
+ +

+it=1, actres=60 msec., avgres=60 msec.
+it=2, actres=50 msec., avgres=55 msec.
+it=3, actres=50 msec., avgres=53 msec.
+it=4, actres=50 msec., avgres=52 msec.
+it=5, actres=50 msec., avgres=52 msec.
+it=6, actres=50 msec., avgres=51 msec.
+...
+it=65, actres=50 msec., avgres=55 msec.
+it=66, actres=50 msec., avgres=55 msec.
+it=67, actres=50 msec., avgres=55 msec.
+it=68, actres=60 msec., avgres=55 msec.
+it=69, actres=60 msec., avgres=55 msec.
+it=70, actres=60 msec., avgres=55 msec.
+
+ +

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

+Interessanterweise bietet die Methode sleep +der Klasse Thread +(sie wird in Abschnitt 22.2.4 +beschrieben) auf aktuellen SUN-JDKs unter Windows mit etwa 1 ms. eine +wesentlich höhere Auflösung als currentTimeMillis. +Diese Eigenschaft ist allerdings nicht dokumentiert und kann von Interpreter +zu Interpreter sehr unterschiedlich sein. Selbst auf ein und derselben +Java-Maschine kann es durch unterschiedliche Lastsituationen zu Abweichungen +kommen. Das folgende Programm ermittelt die Auflösung von sleep:

+ + + + +
 Tipp 
+
+ + +

+ + + + + +
+ +
+001 /* Listing1606.java */
+002 
+003 public class Listing1606
+004 {
+005   public static long testSleep(int millis)
+006   {
+007     final int MINDURATION = 3000;
+008     int cnt = (millis >= MINDURATION ? 1 : MINDURATION/millis);
+009     long start = System.currentTimeMillis();
+010     for (int i = 0; i < cnt; ++i) {
+011       try {
+012         Thread.sleep(millis);
+013       } catch (InterruptedException e) {
+014       }
+015     }
+016     long end = System.currentTimeMillis();
+017     return (end - start) / cnt;
+018   }
+019 
+020   public static void main(String[] args)
+021   {
+022     final int DATA[] = {345, 27, 1, 1962, 2, 8111, 6, 89, 864};
+023     for (int i = 0; i < DATA.length; ++i) {
+024       System.out.println("Aufruf von sleep(" + DATA[i] + ")");
+025       long result = testSleep(DATA[i]);
+026       System.out.print("  Ergebnis: " + result);
+027       double prec = ((double)result / DATA[i] - 1.0) * 100;
+028       System.out.println(" (" + (prec > 0 ? "+": "") + prec + " %)");
+029     }
+030   }
+031 }
+
+
+Listing1606.java
+ +Listing 16.6: Die Auflösung von Thread.sleep bestimmen

+ +

+Ein Aufruf unter dem JDK 1.4 auf einem Windows-98-System im Leerlauf +ergab folgendes Ergebnis: + +

+Aufruf von sleep(345)
+  Ergebnis: 343 (-0.5797101449275366 %)
+Aufruf von sleep(27)
+  Ergebnis: 27 (0.0 %)
+Aufruf von sleep(1)
+  Ergebnis: 1 (0.0 %)
+Aufruf von sleep(1962)
+  Ergebnis: 1920 (-2.1406727828746197 %)
+Aufruf von sleep(2)
+  Ergebnis: 2 (0.0 %)
+Aufruf von sleep(8111)
+  Ergebnis: 8080 (-0.3821970163974897 %)
+Aufruf von sleep(6)
+  Ergebnis: 6 (0.0 %)
+Aufruf von sleep(89)
+  Ergebnis: 89 (0.0 %)
+Aufruf von sleep(864)
+  Ergebnis: 860 (-0.462962962962965 %)
+
+ + + + + +

16.3.6 arraycopy

+ +

+Als letzte Methode der Klasse System +soll arraycopy +vorgestellt werden: +

+ + + + + +
+ +
+public static native void arraycopy(
+   Object src, int src_position,
+   Object dst, int dst_position,
+   int length
+)
+
+
+
+java.lang.System
+ +

+arraycopy +kann dazu verwendet werden, Arrays oder Teile davon zu kopieren. Dabei +können die Elemente sowohl innerhalb desselben Arrays als auch +in ein anderes Array kopiert werden. Falls innerhalb desselben Arrays +kopiert wird, dürfen sich Quell- und Zielbereich auch überlappen. +Die Methode arbeitet sowohl mit elementaren als auch mit Objekttypen, +Ziel- und Quellarray müssen lediglich zuweisungskompatibel sein. +Da die Methode in C bzw. Assembler implementiert ist, arbeitet sie +recht performant. + +

+Als erste Argumente werden das Quellarray src +und die Startposition src_position +angegeben. Anschließend folgen das Zielarray dst +und die Zielposition dst_position. +Als letztes Argument wird die Länge length +des zu kopierenden Bereichs angegeben. Falls die Argumente auf Elemente +zeigen, die außerhalb des Arrays liegen, wird eine Ausnahme +des Typs ArrayIndexOutOfBoundsException +ausgelöst. Falls ein Element aufgrund eines Typfehlers nicht +gespeichert werden kann, gibt es eine Ausnahme des Typs ArrayStoreException. + +

+Das folgende Programm zeigt die Verwendung von arraycopy +an einem einfachen Beispiel: + + +

+ + + + + +
+ +
+001 /* Listing1607.java */
+002 
+003 public class Listing1607
+004 {
+005   public static void main(String[] args)
+006   {
+007     int[] ar = {0,0,0,0,0,0,0,0,0,0};
+008 
+009     for (int i = 0; i < 10; ++i) {
+010       System.arraycopy(ar,0,ar,1,9);
+011       ar[0] = i;
+012     }
+013     System.out.print("ar = ");
+014     for (int i = 0; i < 10; ++i) {
+015       System.out.print(ar[i] + " ");
+016     }
+017     System.out.println("");
+018   }
+019 }
+
+
+Listing1607.java
+ +Listing 16.7: Verwendung von System.arraycopy

+ +

+Das Programm füllt ein 10-elementiges Array von Ganzzahlen, das +zunächst nur Nullen enthält, mit den Zahlen 0 bis 9. Dabei +wird jeweils durch Kopieren der ersten neun Elemente an die zweite +Position des Arrays an der ersten Position Platz gemacht, um dort +den Inhalt des fortlaufenden Schleifenzählers abzulegen. Nach +10 Durchläufen stehen somit die Zahlen 0 bis 9 verkehrt herum +im Array. Die Ausgabe des Programms ist: + +

+ar = 9 8 7 6 5 4 3 2 1 0
+
+ +
+ + + +
 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