Java 系统属性的范围

2022-08-31 17:37:01

在Java中,我们使用System.setProperty()方法来设置一些系统属性。根据本文,系统属性的使用有点棘手。

System.setProperty() 可以是一个邪恶的调用。

  • 它是100%线程敌对的
  • 它包含超全局变量
  • 当这些变量在运行时神秘地变化时,调试非常困难。

我的问题如下。

  1. 系统属性的范围如何?它们是特定于每个虚拟机的,还是具有“超级全局性质”,在每个虚拟机实例上共享相同的属性集?我猜选项1

  2. 是否有任何工具可用于监视运行时更改以检测系统属性中的更改。(只是为了便于问题检测)


答案 1

系统属性的作用域

至少通过阅读 System.setProperties 方法的 API 规范,我无法得到系统属性是否由 JVM 的所有实例共享的答案。

为了找出答案,我编写了两个快速程序,它们将使用相同的键,但不同的值通过 设置系统属性:System.setProperty

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

(请注意,运行上述两个程序会使它们进入无限循环!

事实证明,当使用两个单独的进程运行这两个程序时,一个 JVM 进程中设置的属性值不会影响另一个 JVM 进程的值。java

我应该补充一点,这是使用Sun的JRE 1.6.0_12的结果,并且至少在API规范中没有定义此行为(或者我无法找到它),行为可能会有所不同。

是否有任何工具可以监视运行时更改

据我所知。但是,如果确实需要检查系统属性是否有更改,则可以一次保留 的副本,并将其与另一个调用进行比较 - 毕竟,PropertiesHashtable的子类,因此比较将以类似的方式执行。PropertiesSystem.getProperties

下面是一个程序,它演示了一种检查系统属性是否已更改的方法。可能不是一个优雅的方法,但它似乎完成了它的工作:

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是线程安全的,所以我本来以为也会是这样,事实上,Properties类的API规范也证实了这一点:Properties

此类是线程安全的:多个线程可以共享单个对象,而无需外部同步。Properties


答案 2

系统属性是每个进程的。这意味着它们比静态字段更全局,静态字段是每个类的装入器。例如,如果您有一个运行多个Java webapp的Tomcat实例,每个Webapp都有一个带有静态字段的类,名为,则web应用程序将共享系统属性,但可以在每个web应用程序中设置为不同的值。com.example.ExampleglobalFieldcom.example.Example.globalField


推荐