56

Java では System.setProperty() メソッドを使用して、いくつかのシステム プロパティを設定します。この記事によると、システム プロパティの使用は少しトリッキーです。

System.setProperty() は悪質な呼び出しになる可能性があります。

  • 100% スレッド敵対的です
  • スーパーグローバル変数が含まれています
  • これらの変数が実行時に不可解に変化すると、デバッグが非常に困難になります。

私の質問は次のとおりです。

  1. システム プロパティのスコープはどうですか。それらはすべての仮想マシンに固有のものですか、それともすべての仮想マシン インスタンスで同じプロパティ セットを共有する「スーパー グローバルな性質」を持っていますか? 私はオプション1を推測します

  2. システム プロパティの変更を検出するためにランタイムの変更を監視するために使用できるツールはありますか。(問題の検出を容易にするため)

4

7 に答える 7

51

システム プロパティの範囲

少なくともSystem.setPropertiesメソッドの API 仕様を読んでも、システム プロパティが JVM のすべてのインスタンスで共有されているかどうかはわかりませんでした。

調べるためにSystem.setProperty、同じキーを使用して異なる値を使用して、システム プロパティを設定する 2 つの簡単なプログラムを作成しました。

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) {}
    }
  }
}

(上記の 2 つのプログラムを実行すると、無限ループに陥ることに注意してください!)

2 つの別個のプロセスを使用して 2 つのプログラムを実行するとjava、一方の JVM プロセスで設定されたプロパティの値は、もう一方の JVM プロセスの値に影響しないことがわかります。

これは Sun の JRE 1.6.0_12 を使用した結果であり、この動作は少なくとも API 仕様で定義されていない (または私が見つけられなかった) ことを付け加えておきます。動作は異なる場合があります。

ランタイムの変更を監視するツールはありますか

私の知る限りではありません。ただし、システム プロパティに変更があったかどうかを確認する必要がある場合は、一度に のコピーを保持し、Propertiesそれを別の呼び出しと比較できますSystem.getProperties-- 結局、Propertiesは のサブクラスなHashtableので、比較は次のようになります。同様の方法で実行されます。

以下は、システム プロパティに変更があったかどうかを確認する方法を示すプログラムです。おそらくエレガントな方法ではありませんが、その仕事をしているようです:

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()));
  }
}

プロパティはスレッドセーフではありませんか?

Hashtable は thread-safePropertiesであるため、それも同様であると予想していましたが、実際、Propertiesクラスの API 仕様で確認されています。

このクラスはスレッド セーフです。複数のスレッドがProperties 、外部同期を必要とせずに 1 つのオブジェクトを共有できます。,シリアル化された形式

于 2009-05-26T04:44:38.487 に答える
13

システム プロパティはプロセスごとです。これは、クラスローダーごとの静的フィールドよりもグローバルであることを意味します。たとえば、複数の Java Web アプリケーションを実行する Tomcat の単一インスタンスがあり、それぞれにcom.example.Exampleという名前の静的フィールドを持つクラスがある場合、Web アプリケーションglobalFieldはシステム プロパティを共有しますが、com.example.Example.globalFieldWeb アプリケーションごとに異なる値に設定できます。

于 2013-08-30T00:04:21.353 に答える
5

VM ごとにプロパティのコピーが 1 つあります。それらは、他の静的 (シングルトンを含む) とほぼ同じ問題を抱えています。

ハックとして、コンテキスト(スレッド、コールスタック、時刻など)に応じて異なる応答System.setPropertiesをする のバージョンを呼び出すと思います。Propertiesまた、変更をログに記録することもできますSystem.setPropertySecurityManager関連する権限のログ セキュリティ チェックを設定することもできます。

于 2009-05-26T04:39:53.593 に答える
4

はい、「システム プロパティ」は VM ごとです (ただし、「os.name」、「os.arch」など、ホスト システムに関する情報を含む「魔法の」プロパティがいくつかあります)。

2 番目の質問について: 私はそのようなツールを認識していませんが、システム プロパティが変更されることを懸念している場合は、特別なSecurityManagerを使用して、システム プロパティの変更を防止 (さらには追跡) することができます。

于 2009-05-26T04:38:56.013 に答える
3

それらのスコープは実行中の JVM ですが、いくつかの難解なクラス ローダーの問題がない限り、プロパティ オブジェクトを含む静的変数は同じことを行い、必要に応じて同期またはその他の処理を実行できます。

于 2009-05-26T04:41:28.337 に答える
-1

システム プロパティを使用する動機は何ですか。

構成には Spring を使用し、XML に挿入されたプロパティ ファイルを使用して初期プロパティを設定します。アプリの実行中に構成を変更するには、JMX を使用します。

もちろん、プロパティファイルやxmlベースの構成などを使用してJavaで構成を変更する方法は他にもたくさんあります。

于 2009-05-26T05:50:39.093 に答える