wake-up-neo.com

Geltungsbereich der Java-Systemeigenschaften

In Java verwenden wir die Methode System.setProperty (), um einige Systemeigenschaften festzulegen. Laut diesem Artikel ist die Verwendung von Systemeigenschaften etwas kompliziert.

System.setProperty () kann ein böser Aufruf sein. 

  • Es ist 100% fadenfeindlich
  • Es enthält super-globale Variablen
  • Es ist äußerst schwierig zu debuggen, wenn diese Variablen mysteriös sind zur Laufzeit ändern.

Meine Fragen lauten wie folgt.

  1. Wie sieht es mit dem Umfang der Systemeigenschaften aus? Sind sie für jede virtuelle Maschine spezifisch oder haben sie eine "Super-Global-Eigenschaft", die die gleichen Eigenschaften für jede einzelne virtuelle Maschineninstanz verwendet? Ich denke die Option 1

  2. Gibt es Werkzeuge, mit denen die Laufzeitänderungen überwacht werden können, um die Änderungen in den Systemeigenschaften zu erkennen? (Nur für die einfache Problemerkennung)

Umfang der Systemeigenschaften

Zumindest durch das Lesen der API-Spezifikationen für die Methode System.setProperties konnte ich keine Antwort erhalten, ob die Systemeigenschaften von allen Instanzen der JVM gemeinsam genutzt werden oder nicht.

Um dies herauszufinden, habe ich zwei Schnellprogramme geschrieben, die die Systemeigenschaft über System.setProperty mit demselben Schlüssel und unterschiedlichen Werten festlegen:

class T1 {
  public static void main(String[] s) {
    System.setProperty("dummy.property", "42");

    // Keep printing value of "dummy.property" forever.
    while (true) {
      System.out.println(System.getProperty("dummy.property"));
      try {
        Thread.sleep(500);
      } catch (Exception e) {}
    }
  }
}

class T2 {
  public static void main(String[] s) {
    System.setProperty("dummy.property", "52");

    // Keep printing value of "dummy.property" forever.
    while (true) {
      System.out.println(System.getProperty("dummy.property"));
      try {
        Thread.sleep(500);
      } catch (Exception e) {}
    }
  }
}

(Beachten Sie, dass die beiden oben genannten Programme dazu führen, dass sie in eine Endlosschleife geraten!)

Es stellt sich heraus, dass beim Ausführen der beiden Programme mit zwei separaten Java-Prozessen der Wert für die in einem JVM-Prozess festgelegte Eigenschaft den Wert des anderen JVM-Prozesses nicht beeinflusst.

Ich sollte hinzufügen, dass dies die Ergebnisse für die Verwendung von Suns JRE 1.6.0_12 ist. Dieses Verhalten ist zumindest in den API-Spezifikationen nicht definiert (oder ich konnte es nicht finden), das Verhalten kann variieren.

Gibt es Werkzeuge zur Überwachung von Laufzeitänderungen

Nicht meines Wissens. Wenn Sie jedoch prüfen müssen, ob Änderungen an den Systemeigenschaften vorgenommen wurden, können Sie eine Kopie der Variable Properties gleichzeitig speichern und mit einem anderen Aufruf von System.getProperties - andernfalls - Properties vergleichen Unterklasse von Hashtable , so würde der Vergleich auf ähnliche Weise durchgeführt werden.

Im Folgenden finden Sie ein Programm, mit dem Sie prüfen können, ob Änderungen an den Systemeigenschaften vorgenommen wurden. Wahrscheinlich keine elegante Methode, aber es scheint ihre Aufgabe zu erfüllen:

import Java.util.*;

class CheckChanges {

  private static boolean isDifferent(Properties p1, Properties p2) {
    Set<Map.Entry<Object, Object>> p1EntrySet = p1.entrySet();
    Set<Map.Entry<Object, Object>> p2EntrySet = p2.entrySet();

    // Check that the key/value pairs are the same in the entry sets
    // obtained from the two Properties.
    // If there is an difference, return true.
    for (Map.Entry<Object, Object> e : p1EntrySet) {
      if (!p2EntrySet.contains(e))
        return true;
    }
    for (Map.Entry<Object, Object> e : p2EntrySet) {
      if (!p1EntrySet.contains(e))
        return true;
    }

    return false;
  }

  public static void main(String[] s)
  {
    // System properties prior to modification.
    Properties p = (Properties)System.getProperties().clone();
    // Modification of system properties.
    System.setProperty("dummy.property", "42");
    // See if there was modification. The output is "false"
    System.out.println(isDifferent(p, System.getProperties()));
  }
}

Properties ist nicht threadsicher?

Hashtableist Thread-sicher, also hatte ich erwartet, dass Properties genauso gut wäre, und tatsächlich bestätigen die API-Spezifikationen für die Properties -Klasse:

Diese Klasse ist threadsicher: multiple Threads können sich eine einzige Properties.__ teilen. Objekt ohne die Notwendigkeit eines externen Synchronisation., Serialisiertes Formular

38
coobird

Die Systemeigenschaften werden pro Prozess festgelegt. Dies bedeutet, dass sie globaler sind als statische Felder, die pro Klassenlader sind. Wenn Sie beispielsweise eine einzige Instanz von Tomcat haben, auf der mehrere Java-Webapps ausgeführt werden, von denen jede über eine Klasse com.example.Example mit einem statischen Feld mit dem Namen globalField verfügt, verwenden die Webapps die Systemeigenschaften. In com.example.Example.globalField kann jedoch jeweils ein anderer Wert festgelegt werden Web-App.

8
Max Nanasy

Es gibt eine Kopie der Eigenschaften pro VM. Sie haben ähnliche Probleme wie andere Statiken (einschließlich Singletons).

Ich denke, als Hack rufen Sie System.setProperties zu einer Version von Properties auf, die je nach Kontext (Thread, Aufrufstack, Uhrzeit usw.) unterschiedlich reagiert. Es könnte auch Änderungen mit System.setProperty protokollieren. Sie können auch eine SecurityManager-Sicherheitsprüfung für die entsprechenden Berechtigungen festlegen.

Ihr Geltungsbereich ist die ausgeführte JVM. Wenn Sie jedoch nicht über einen esoterischen Klassenladeprogramm verfügen, wird eine statische Variable mit einem Eigenschaftenobjekt das gleiche tun. Außerdem können Sie synchronisieren oder tun, was immer Sie benötigen.

3
Yishai

Ja, "Systemeigenschaften" sind pro VM (obwohl es einige "magische" Eigenschaften gibt, die Informationen über das Host-System enthalten, z. B. "os.name", "os.Arch" usw.).

Zu Ihrer zweiten Frage: Ich kenne ein solches Tool nicht. Wenn Sie jedoch Bedenken gegen die Änderung der Systemeigenschaften haben, können Sie einen speziellen SecurityManager verwenden, um Änderungen der Systemeigenschaften zu verhindern (und möglicherweise zu verfolgen).

2

Wenn Sie eine neue JVM starten, wird eine Kopie der Umgebungsvariablen erstellt und für den gesamten Lebenszyklus verwendet. Wenn Sie also Änderungen an dieser Umgebung vornehmen, bleiben sie darauf beschränkt. Das seltsame Verhalten, das ich erlebt habe und bei dem ich nachforsche, ist etwas anders: Wenn ich eine JVM starte, die einige Umgebungsvariablen (Argument -D in cmd-Zeile) deklariert, die das Verhalten der in meinen Anwendungen verwendeten Bibliotheken beeinflussen. Wenn ich jedoch innerhalb des Java-Codes (wo er sichtbar ist) Änderungen daran vornehme, scheinen diese Änderungen das Verhalten von Bibliotheken nicht zu beeinflussen. Das Seltsame ist, dass wir in derselben JVM sind!

0
Robin73

Sie sagen nicht, was Ihre Motivation für die Verwendung von Systemeigenschaften ist.

Wir verwenden Spring für unsere Konfiguration und legen die anfänglichen Eigenschaften mithilfe einer Eigenschaftendatei fest, die in das XML eingefügt wird. Konfigurationsänderungen während der Ausführung der App werden mithilfe von JMX vorgenommen.

Es gibt natürlich viele andere Möglichkeiten, die Konfiguration in Java mithilfe der Eigenschaftendatei, der XML-basierten Konfiguration usw. zu ändern.

0
Fortyrunner